docker放浪記2・dockerでSQLServer

Masami Koganei
合同会社 Interrupt MEMBER

第二回dockerでSQLServer

DBならMySQLをやると思っただろ。違うんだな、これが

さて前回、基本アプリのDockerDesktopとVsCodeをインストールしたのですがVsCodeにはdocker拡張機能やSQL-Server拡張機能もあるので、是非使ってみましょう。

RDBMSとは?

SQLServerもMySQLもリレーショナル データベース(RDBMS)と呼ばれます。

詳しくはこちらを参照して見てください。

第二回はdocker-composeを使ってこのDB環境を作り上げて初期データを投入、そしてVsCodeから接続して見ましょう。

VsCodeでフォルダーを開く

今回も例によって適当なフォルダー(mssqlなど)を作成し、VsCodeのエクスプローラーで開いて見ましょう。

ここを参照にしてプロジェクトを作って見ました。

ただわたしの環境ではうまく動作しなかったので、いくつか手を加えてあります。

  • 親ディレクトリ(mssqlなど)
    • init.db.d(DBを初期化するシェルなどを配置するフォルダです)
      • entrypoint.sh(DB初期化シェル)
      • init.sql(DB初期データSQL)
    • docker-compose.yml

今回はインストール等必要ないみたいですのでDockerFileは使いません。

docker-compose.yml

以下docker-compose.ymlの例です。

version: '3'

services:
  mssql:
    image: mcr.microsoft.com/mssql/server:2022-latest # イメージを直接指定
    cap_add:
      - SYS_PTRACE # 追加 システムアタッチ
    security_opt:
      - seccomp:unconfined # 追加 システムアタッチ
    user: root # ルートユーザーで実行
    container_name: mssql # コンテナ名を指定
    environment: # 環境変数を設定
      - ACCEPT_EULA=Y # エンドユーザーライセンス契約に同意
      - SA_PASSWORD=Passw0rd # パスワードを設定
      - MSSQL_PID=Express # エディションを設定
      - MSSQL_TCP_PORT=1433 # 使用するポートを設定
      - MSSQL_LCID=1041 # 日本語に設定
      - TZ="Asia/Tokyo" # タイムゾーン設定
      - Japanese_CI_AS=Japanese_CI_AS # 照合順序を指定
    ports: # ポート番号を指定(ホスト:コンテナ)
      - 1433:1433 
    volumes: # マッピングを指定
      - ./init.db.d:/docker-initdb.d # 初期化用SQLとSQL Server起動スクリプト
      - mssql_data:/var/opt/mssql/data # dataの永続化
      - mssql_log:/var/opt/mssql/log # logの永続化
      - mssql_secrets:/var/opt/mssql/secrets # secretsの永続化
    command: ["/bin/bash", "-c", "chmod +x /docker-initdb.d/entrypoint.sh && /docker-initdb.d/entrypoint.sh"] # SQL Server起動スクリプトを実行
volumes:
  mssql_data:
  mssql_log:
  mssql_secrets:

ほぼ参照元のままなのですが、いくつか動作しなかったところ(システムアタッチなど)を修正しました。

元になるイメージはM1だと動作しないらしいのですが、前回のようにDockerDesktopでUseVirtualization frameworkをオンにしたら動いたのでそのまま使用しています。

dockerでDB環境を動作させる場合、永続化(dockerコンテナを停止させた時にDBのデータが消えないようにする)という作業が必要なのですがそれをvolumesでローカルに関連づけています

entrypoint.sh

実行シェルです。そのためdocker-compose.ymlのcommandで実行権限を与えてから実行しています。

#!/bin/bash

# SQL Serverをフォアグラウンドで実行
echo "Waiting for SQL Server to start..."
/opt/mssql/bin/sqlservr & MSSQL_PID=$!

# SQL Serverの起動を待機
#while ! /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Passw0rd -Q "SELECT 1" > /dev/null 2>&1; do
while ! /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P Passw0rd -C -Q "SELECT 1" > /dev/null 2>&1; do
    sleep 1
done
echo "SQL Server started."

# 初期化用SQLを実行
echo "Initializing database..."
#/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Passw0rd -i /docker-initdb.d/init.sql
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P Passw0rd -i /docker-initdb.d/init.sql -C
echo "Database initialized."

# バックグラウンドで実行中のSQL Serverのプロセスを待機
wait $MSSQL_PID
# SQL Serverをフォアグラウンドで実行
echo "Waiting for SQL Server to start..."
/opt/mssql/bin/sqlservr & MSSQL_PID=$!

# SQL Serverの起動を待機
while ! /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P Passw0rd -C -Q "SELECT 1" > /dev/null 2>&1; do
    sleep 1
done
echo "SQL Server started."

# 初期化用SQLを実行
echo "Initializing database..."
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P Passw0rd -i /docker-initdb.d/init.sql -C
echo "Database initialized."

# バックグラウンドで実行中のSQL Serverのプロセスを待機
wait $MSSQL_PID

これもいくつかdockerデバッグをしながら修正しました。コンテナが起動中であればVsCodeやターミナルなどから

docker exec -it mssql /bin/bash

のようにしてdockerコンテナに入り

cat /var/opt/mssql/log/errorlog.loc

のようにしてログを見てデバッグしました。

init.sql

-- データベースが存在しない場合のみ作成
IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = 'test_db')
BEGIN
    CREATE DATABASE test_db;
END
GO

USE test_db;
GO

-- テーブルが存在しない場合のみ作成
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'UserInfo' AND type = 'U')
BEGIN
    CREATE TABLE UserInfo (
        [id] INT NOT NULL IDENTITY(1,1)
        , [name] VARCHAR(MAX)
        , PRIMARY KEY (ID)
    );

    INSERT INTO UserInfo (name) VALUES('taro');
    INSERT INTO UserInfo (name) VALUES('jiro');
    INSERT INTO UserInfo (name) VALUES('saburo');
END
GO

テーブル名でSQLエラーが出たのでUserInfoにかえました。

実行してみるっ

起動方法は前回と同じでVsCodeでターミナルを開き

docker-compose -p <コンテナ名> up -d

とやってみましょう

うまく行けばMAC上でSQLServerが起動します。

RecoveryUnit::Shutdown. IsOnline: 02024-12-06 00:20:28.39 spid28s     Attribute synchronization initialized
2024-12-06 00:20:28.39 spid28s     Attribute synchronization initialized
2024-12-06 00:20:28.39 spid28s     Attribute synchronization manager initialized
2024-12-06 00:20:28.40 spid28s     Attribute synchronization manager initialized

DockerDesktopでこんなログが出ればOKです。

VsCodeで接続してみるっ

といっても同じマシン内なので簡単だろう、と思うのですが、意外と苦労しました。

まずVsCodeに拡張機能のsql serverをインストールしましょう

s06

接続先ホストはlocalhost,1433になります。

ユーザーはsa、パスワードはdocker-compose.ymlのSA_PASSWORDで指定しているものになります。

s05

これでテーブルUserInfoの内容が見れればOKです。