TL;DR
-
Docker
ではディレクトリをマウントするとコンテナ内の情報が上書きされてしまうが、bind
でファイルをマウントするなら上書きされない -
MySQL
公式イメージでは、docker-entrypoint-initdb.d
に置いた.sh
ファイルはコンテナ起動時に実行される - よって、
DDL
を入れたディレクトリを任意のパスにマウントし、投入用スクリプトをdocker-entrypoint-initdb.d
にbind
でマウントすることで、docker-entrypoint-initdb.d
にDDL
をマウントしない形で初期データを投入できる
本文
やりたかったこと
コンテナ内のdocker-entrypoint-initdb.d
を上書きせず、かつディレクトリをマウントするのと同じような使い勝手で、コンテナ起動時に初期化用DDL
を実行したかったです。
やり方
冒頭で書いた通り、ファイルをマウントする形であれば、コンテナ内のdocker-entrypoint-initdb.d
は上書きされません。
また、MySQL
公式イメージでは、docker-entrypoint-initdb.d
に置いた.sh
ファイルはコンテナ起動時に実行されます。
よって、任意のディレクトリとしてDDL
を入れたディレクトリをマウントし、その投入はdocker-entrypoint-initdb.d
にマウントしたシェルスクリプトで行えばできます。
以下は投入スクリプトの例です。
# !/bin/sh
# ---
# MySqlコンテナの/docker-entrypoint-initdb.dにファイルとしてマウントすることで
# そのコンテナの/tmp/init.dにマウントされた差分DDLをMySQLに投入する
#
# /tmp/init.dにファイルが存在しない場合はエラーとなる
# ---
ls -1 /tmp/init.d/*.sql | while read file
do
mysql -uroot -proot < $file
done
一連の実行はファイル名のアルファベット順であるため、マウント時のファイル名を調整すれば、順序の制御も可能です。
例えばマウントするファイル名のプレフィックスをzzz-
とすることで、最後に実行されるようにできます。
# 略(※イメージです、動かして試してはいません)
volumes:
- type: bind # 投入シェルのマウント、実行順を最後にするためzzz-というプレフィックスを指定している
source: ./init.sh
target: /docker-entrypoint-initdb.d/zzz-init.sh
- ./init.d:/tmp/init.d/ # DDLを投入スクリプトに合わせ/tmp/init.dにマウント
これが必要になった背景
docker-entrypoint-initdb.d
に初期データが入っている形式のイメージを利用する必要が有り、ここにディレクトリをマウントすることができなかったためです。
素直にdocker-entrypoint-initdb.d
にファイルを配置する方法でやるならDDL
ファイルを個別にマウントする必要が有るため、ディレクトリでまとめてマウントする方法を検討してこのやり方に行きつきました。
参考にさせて頂いた内容
-
mysql - Docker Hub
-
Initializing a fresh instance
の章に.sh
や.sql
の実行に関する記述が有ります
-