【Docker】【MySQL】MySQL イメージのコンテナを初期起動した際に自動で *.sql ファイル内の SQL 文を実行する

  • 2022年4月25日
  • 2022年4月25日
  • Docker, SQL

 Docker は仮想環境を用意してその中で色々する仕組みです。MySQL を動かすこともできます。MySQL の公式イメージを使ってコンテナを立ち上げる際、自動で SQL を実行する方法を紹介します。

Mysql – Official Image | Docker Hub

 上記リンクからつながるイメージの説明のの Initializing a fresh instance には次の様に記述されています。

コンテナの初回起動時、指定された名前の新しいデータベースが作成され、与えられた設定値で初期化されます。
When a container is started for the first time, a new database with the specified name will be created and initialized with the provided configuration variables.

さらに、/docker-entrypoint-initdb.d 内の拡張子が .sh, .sql, .sql.gz のファイルがアルファベット順で実行されます。
Furthermore, it will execute files with extensions .sh, .sql and .sql.gz that are found in /docker-entrypoint-initdb.d. Files will be executed in alphabetical order.

このディレクトリにSQLダンプをマウントすることによって、簡単にmysqlサービスを追加でき、完成したデータ付のカスタムイメージを提供することができます。
You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data.

SQLファイルはデフォルトでMYSQL_DATABASEで指定されたデータベースに挿入されます。
SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.

 三文目の訳がすごく怪しいですが要はコンテナの中の /docker-entrypoint-initdb.d に SQL ファイルをおけば他の設定値に合わせていい感じに自動でファイル名辞書順でSQLが実行され、実行用のSQLファイルをイメージに組み込んだカスタムイメージを配るとみんな便利、ということです。

 この機能は例えば、次の様に使えます。

# ファイル構造
.
│  .env
│  docker-compose.yml
│
└─docker
    └─mysql
       │  Dockerfile
       │  my.cnf
       │  
       └─init-sql
               20220425141132_database.sql
               20220425141144_database.sql
# docker-compose.yml
version: "3"
services:
  mysql:
    build:
      context: ./docker/mysql # 使う Dockerfile のあるディレクトリ
    volumes:
      - db-store:/var/lib/mysql # 名前付きコンテナでデータベースの中身を永続化
      - type: bind # エラーログはすぐ見れる様にマウント
        source: "./docker/log/mysql/mysql-error.log"
        target: "/var/log/mysql/mysql-error.log"
    environment:
      - MYSQL_DATABASE=${DB_DATABASE} # デフォルトのデータベース名
      - MYSQL_USER=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
      - TZ=${APP_TZ:-Asia/Tokyo} # タイムゾーン
    ports:
      - ${DOCKER_DB_PORT:-3306}:3306 # 外部公開ポート

volumes:
  db-store:

# .env
APP_TZ=Asia/Tokyo
DOCKER_DB_PORT=3566
DB_DATABASE=demo
DB_USERNAME=demouser
DB_PASSWORD=demopassword
# Dockerfile
FROM mysql:8.0

# MySQL 設定ファイルをコピー
COPY my.cnf /etc/mysql/conf.d/my.cnf
# データ初期化用 SQL ファイルらをコピー
COPY ./init-sql /docker-entrypoint-initdb.d

 これで、docker/mysql 以下においた MySQL 設定ファイルである my.cnf とdocker/mysql/init-sql 以下に置いた *.sql ファイルがコンテナ起動後の MySQL に組み込まれます。コンテナ起動時には次の様なログが流れます。

> docker-compose logs mysql
Attaching to demo_mysql_1
mysql_1  | 2022-04-25 14:16:47+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.28-1debian10 started.
mysql_1  | 2022-04-25 14:16:47+09:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
mysql_1  | 2022-04-25 14:16:47+09:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.28-1debian10 started.
mysql_1  | 2022-04-25 14:16:47+09:00 [Note] [Entrypoint]: Initializing database files
mysql_1  | 2022-04-25 14:16:51+09:00 [Note] [Entrypoint]: Database files initialized
mysql_1  | 2022-04-25 14:16:51+09:00 [Note] [Entrypoint]: Starting temporary server
mysql_1  | 2022-04-25 14:16:52+09:00 [Note] [Entrypoint]: Temporary server started.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
mysql_1  | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: Creating database demo
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: Creating user demouser
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: Giving user demouser access to schema demo
mysql_1  |
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/20220425141132_database.sql
mysql_1  |
mysql_1  |
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/20220425141144_database.sql
mysql_1  |
mysql_1  |
mysql_1  | 2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: Stopping temporary server
mysql_1  | 2022-04-25 14:16:55+09:00 [Note] [Entrypoint]: Temporary server stopped
mysql_1  |
mysql_1  | 2022-04-25 14:16:55+09:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
mysql_1  |

 Warningが怪しいですが、一応日本時間で動きました。加えて期待通り、ログ内に2022-04-25 14:16:54+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/20220425141132_database.sqlとSQLを実行したという履歴があります。この様にイメージ内の特定の場所にファイルを置き、コンテナを生成するとそれに沿った MySQL コンテナを動かせます。またこのコンテナの中の設定ファイルと /docker-entrypoint-initdb.d/ の中にはコピーしたファイルが残っています。これを利用して次の様にイメージを生成すれば、次は Dockerfile や付随するファイル抜きのベースイメージとしてデータ付きの改造版 MySQL イメージを使えます。

> docker ps | grep mysql # 作ったコンテナのコンテナIDを得る
821e31c2e5a0   demo_mysql                "docker-entrypoint.s??"   About an hour ago   Up 12 minutes          33060/tcp, 0.0.0.0:3566->3306/tcp                demo_mysql_1
> docker commit 821e31c2e5a0 custom_mysql:1.0   # コンテナIDからコンテナの現状態をイメージ化
sha256:6137f657ce1362d1c5f5c612b02a4c2bffb0da5027255828b7a4a66664400dbc
> docker images | grep custom # イメージができたことを確認
custom_mysql                                      1.0                     6137f657ce13   48 minutes ago      521MB
> 
>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG