6
Help us understand the problem. What are the problem?

posted at

docker-compose起動時に、init.dbのSQLが実行されない場合の対処

事象

docker-compose upで各コンテナを起動した際に、下記のdocker-compose.ymlでDBに初期データを投入しようとしていました。
しかしinitdbにCREATE TABLEを書き込んでdocker-compose down ⇒ docker-compose upしてもSQLが実行されず...。

docker-compose.ymlの記載内容

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

以上手順で、無事に初回起動時の初期データ投入を実行することができました:v:

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
6
Help us understand the problem. What are the problem?