#事象
docker-compose upで各コンテナを起動した際に、下記のdocker-compose.ymlでDBに初期データを投入しようとしていました。
しかしinitdbにCREATE TABLEを書き込んでdocker-compose down ⇒ docker-compose upしてもSQLが実行されず...。
###docker-compose.ymlの記載内容
version: "3"
services:
db:
image: mariadb:10.5.11
volumes:
- ./docker_resource/db/initdb:/docker-entrypoint-initdb.d // これを実行したい
restart: always
environment:
MYSQL_ROOT_PASSWORD: ********
MYSQL_DATABASE: hogehoge
LANG: C.UTF-8
TZ: Asia/Tokyo
ports:
- "3306:3306"
#そもそも何故volumesに記載するとコンテナ起動時に実行できるのか
###volumesの役割
volumesに<ホストのディレクトリ:コンテナのディレクトリ>
の形式で記載することでホスト上のボリュームをコンテナにマウントすることができます。
マウントとは二つのディレクトリを同期することで、マウントを行うことでコンテナ上からホスト上(自分のPC上)にあるファイルを読み込んだり書き込んだりすることができるようになります。
上記のコード例でいうと、ホスト上の./docker_resource/db/initdbを/docker-entrypoint-initdb.dと同期することで、起動したDBコンテナからinitdbを読み込むことができるようになるというわけです。
###自動的に実行される理由
/ docker-entrypoint-initdb.dに拡張子が.sh .sqlのファイルを配置しておくと、DBコンテナ開始時にファイルをアルファベット順に実行してくれます。上記のvolumesで/ docker-entrypoint-initdb.dにはホスト上の./docker_resource/db/initdbがマウントされているので、ホスト上の./docker_resource/db/initdbにsqlファイルを置いておけばコンテナ開始時に自動的にSQLが実行されることになります!
引用:https://hub.docker.com/_/mysql/
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. 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. You can easily populate your mysql services by mounting a SQL dump into that directory and provide custom images with contributed data. SQL files will be imported by default to the database specified by the MYSQL_DATABASE variable.
Google翻訳:
*新しいインスタンスの初期化
コンテナーが初めて開始されると、指定された名前の新しいデータベースが作成され、指定された構成変数で初期化されます。さらに、/ docker-entrypoint-initdb.dにある拡張子.sh、.sql、および.sql.gzのファイルを実行します。ファイルはアルファベット順に実行されます。 SQLダンプをそのディレクトリにマウントし、提供されたデータを含むカスタムイメージを提供することで、mysqlサービスに簡単にデータを入力できます。 SQLファイルは、デフォルトでMYSQL_DATABASE変数で指定されたデータベースにインポートされます。
#何故SQLが実行されなかったか
###コンテナを停止してもボリュームは削除されず、コンテナ開始時に更新前のファイルを読み込んでしまうため
コンテナを破棄してもボリュームは残存します。
###docker volumeの確認
> docker volume ls // docker volumeの一覧を表示する
DRIVER VOLUME NAME
local 1f9...
local 5e0...
> docker-compose down // docker-composeの終了
Stopping hogehoge_1 ... done
Stopping fugafuga_1 ... done
> docker volume ls
DRIVER VOLUME NAME
local 1f9... //消えてない!!
local 5e0... //消えてない!!
volumesに記載したボリュームが残っている場合、docker-compose up時にそのファイルを読み込み、新たにマウントは行われません。ホスト上のファイルを更新した場合は古いボリュームを削除し、ボリュームのマウントからやり直す必要がありました。
###docker volumeの削除
> docker volume ls
DRIVER VOLUME NAME
local 1f9...
local 5e0...
> docker volume rm <VOLUME NAME> //docker volumeの削除
> docker volume rm $(docker volume ls -qf dangling=true) //docker volumeの全削除
// コンテナ削除時にError response from daemon: unable to remove volume: remove XXX: volume is in use が出て削除できない場合
> docker system prune
> docker volume ls // docker vokumeが削除されており、表示されないことを確認
DRIVER VOLUME NAME
> docker-compose up
以上手順で、無事に初回起動時の初期データ投入を実行することができました