LoginSignup
24
28

More than 1 year has passed since last update.

DockerでSQLServerを起動&初期データ登録

Last updated at Posted at 2020-09-18

SQLServerのDockerコンテナに初期データを投入して起動します。
マイクロソフト公式のDockerイメージを使用します。MySQLだと初期データ投入の仕組みが初めから組み込まれていますが、SQLServerにはそれないのでシェルを作成しました。

Microsoft SQL Server Dockerイメージ(https://hub.docker.com/_/microsoft-mssql-server
参考:公式からリンクされているデータ投入サンプル(https://github.com/twright-msft/mssql-node-docker-demo-app
Qiita Docker for Windowsを使って、SQL Server Express を使用する

ディレクトリー構成

|- docker-compose.yml
|- docker
    |- mssqlserver
        |- Dockerfile
        |- initdb.d
            |- entrypoint.sh
            |- import-data.sh
            |- demo.sql
            |- Demo.dbo.DEMO.csv
        |- data
        |- log
        |- secrets

各ファイル

docker-compose.yml

environmentで設定しているSQL Serverの環境変数についてはこちらを参照。

docker-compose.yml
version: '3'

services:
  mssql:
    build:
      context: ./docker/mssqlserver/
    image: mssql
    ports:
      - 1433:1433
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=56CFUVzh # パスワードポリシー(https://docs.microsoft.com/ja-jp/sql/relational-databases/security/password-policy?view=sql-server-ver15)
      - MSSQL_PID=Express # SQL Serverのエディションまたはプロダクトキー
      - MSSQL_LCID=1041 # ロケールID 日本語 (https://www.ryadel.com/en/microsoft-windows-lcid-list-decimal-and-hex-all-locale-codes-ids/)
      - MSSQL_COLLATION=Japanese_CI_AS # 照合順
      - DB_NAME=DEMO # 初回起動時のDB存在判定のために使用します。
    volumes:
      - ./docker/mssqlserver/initdb.d:/docker-entrypoint-initdb.d
      - ./docker/mssqlserver/data:/var/opt/mssql/data
      - ./docker/mssqlserver/log:/var/opt/mssql/log
      - ./docker/mssqlserver/secrets:/var/opt/mssql/sec

Dockerfile

初期データと投入用シェルスクリプトをコピーし、entrypoint.shを呼び出します。
(ちなみにEXPOSEはただのドキュメントらしいです。)

Dockerfile
FROM mcr.microsoft.com/mssql/server:2017-latest

USER root
SHELL ["/bin/bash", "-c"]

WORKDIR /docker-entrypoint-initdb.d
COPY ./initdb.d/ /docker-entrypoint-initdb.d/
RUN chmod -R +x /docker-entrypoint-initdb.d

EXPOSE 1433

ENTRYPOINT ["/bin/bash", "./entrypoint.sh"]

entrypoint.sh

データ登録のシェルとSQLServerを同時起動します。ここで少しはまったのですがSQLServerの起動を先にするとimport-data.sh実行後コンテナが停止してしまいます。SQLServerを後ろにするとコンテナは起動し続けます。(つまりDockerは一番最後に実行したプロセスが生きているかどうかでコンテナを停止するのか判断している?)
→これは単純にどちらをバックグラウンドで実行するかの違いでした。SQLServerをバックグラウンドで実行してしまっているので、import-data.shが終わるとプロセスID=1のこのシェルが終了します。PID=1のプロセスが停止するとDockerが停止します。詳しくはコメント欄の2件目を参照してください。

Initialize MS SQL in Docker container - create database at startup(https://www.softwaredeveloper.blog/initialize-mssql-in-docker-container

entrypoint.sh
#!/bin/bash

LOG_OUT=/var/opt/mssql/log/init-stdout.log
LOG_ERR=/var/opt/mssql/log/init-stderr.log

exec 1>>$LOG_OUT
exec 2>>$LOG_ERR

# SQL Serverが前だとコンテナが停止してしまいます。
#/opt/mssql/bin/sqlservr & /docker-entrypoint-initdb.d/import-data.sh
/docker-entrypoint-initdb.d/import-data.sh & /opt/mssql/bin/sqlservr

import-data.sh

SQLServerと同時起動するので、インスタンスが起動するまで初めに20秒スリープします。また、SQLやCSVインポートを実行してエラーの場合1秒待って再実行するようにしています。

import-data.sh
#!/bin/bash
sleep 20

if [ `ls -U1 /var/opt/mssql/data | grep $DB_NAME | wc -l` -eq 0 ]; then
    cd /docker-entrypoint-initdb.d
    sql_files=`ls *.sql`

    for file in $sql_files;
    do
        for i in {1..30};
        do
            /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -i $file
            if [ $? -eq 0 ]
            then
                echo "${file} completed."
                break
            else
                echo "${file} failed."
                sleep 1
            fi
        done
    done

    csv_files=`ls *.csv`
    for file in $csv_files;
    do
        for i in {1..30};
        do
            table_name=`basename $file .csv`
            /opt/mssql-tools/bin/bcp $table_name in $file -c -t',' -S localhost -U sa -P $SA_PASSWORD
            if [ $? -eq 0 ]
            then
                echo "${file} completed."
                break
            else
                echo "${file} failed."
                sleep 1
            fi
        done
    done
fi
24
28
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
28