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 >