研修でのアプリ作成の開発環境に、これまでに用意いただいて使用していた、あり合わせの Dockerfile 、 docker-compose.yml を使用していました。
コードレビューしていただいた時に「ところで、Dockerコンテナを作成・起動した時に、MySQLのデータベースにテーブルが作成されるのはなんで?」と確認の質問をいただき、さっぱり答えられなかったので、 答えられるよう理解するためのアウトプットです。
1. 理解したいこと
- 下記Docker関連のファイルの中で、DBのテーブル(下記の docker/mysql/initdb.d/01_products.sql )を自動作成してくれている仕組みを理解したい。
docker-compose.yml
version: "3.6"
services:
web:
build:
context: .
dockerfile: ./docker/nginx/Dockerfile
depends_on:
- app
ports:
- ${WEB_PORT:-80}:80
volumes:
- ./doc_root/public:/var/www/sample-app/public
app:
build:
context: .
dockerfile: ./docker/php/Dockerfile
environment:
MYSQL_DATABASE: ${DB_NAME:-sample_app}
MYSQL_USER: ${DB_USER:-db_user}
MYSQL_PASSWORD: ${DB_PASS:-secret}
depends_on:
- db
links:
- db:mysql
volumes:
- ./docker/php/php.ini:/usr/local/etc/php/php.ini
- ./doc_root:/var/www/sample-app
db:
build:
context: .
dockerfile: ./docker/mysql/Dockerfile
environment:
MYSQL_DATABASE: ${DB_NAME:-sample_app}
MYSQL_USER: ${DB_USER:-db_user}
MYSQL_PASSWORD: ${DB_PASS:-secret}
MYSQL_ROOT_PASSWORD: ${DB_PASS:-secret}
ports:
- ${DB_PORT:-3306}:3306
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
driver: local
docker/mysql/Dockerfile
FROM mysql:5.6
# timezone environment
ENV TZ=Asia/Tokyo
COPY ./docker/mysql/my.cnf /etc/mysql/conf.d/my.cnf
COPY ./docker/mysql/initdb.d /docker-entrypoint-initdb.d
CMD [ "mysqld", "--character-set-server=utf8", "--collation-server=utf8_unicode_ci" ]
docker/mysql/initdb.d/01_products.sql
SET CHARACTER_SET_CLIENT = utf8;
SET CHARACTER_SET_CONNECTION = utf8;
CREATE TABLE products (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
price INTEGER NOT NULL,
image VARCHAR(256),
delete_flag BOOLEAN NOT NULL DEFAULT FALSE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
docker/mysql/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
[client]
default-character-set=utf8mb4
2. わからないこと
- 上記Docker関連のファイルの中で、テーブルを自動作成してくれている仕組みがわからない。
docker/mysql/Dockerfile のテーブル作成に関連すると思う箇所
COPY ./docker/mysql/initdb.d /docker-entrypoint-initdb.d
3. 調べたこと
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 yourmysql
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 theMYSQL_DATABASE
variable.(以下、DeepL翻訳)
新しいインスタンスの初期化コンテナが初めて起動されると、指定された名前の新しいデータベースが作成され、提供された設定変数で初期化されます。さらに、
/docker-entrypoint-initdb.d
にある拡張子.sh
,.sql
,.sql.gz
のファイルがアルファベット順で実行されます。このディレクトリにSQLダンプをマウントすることで、簡単にmysql
サービスにデータを取り込むことができ、カスタムイメージにデータを提供することができます。SQLファイルはデフォルトでMYSQL_DATABASE
変数で指定されたデータベースにインポートされます。
上記のとおり、/docker-entrypoint-initdb.d
にある拡張子 .sql
を実行するようになっており、
COPY ./docker/mysql/initdb.d /docker-entrypoint-initdb.d
でコピーされたファイルを、実行してくれていることがわかりました!
その他、調べたこと
mysqld
CMD [ "mysqld", "--character-set-server=utf8", "--collation-server=utf8_unicode_ci" ]
mysqld
とは
mysqld
は、MySQL サーバーとも呼ばれ、MySQL インストールでのほとんどの作業を実行するメインプログラムです。MySQL サーバーは、データベースおよびテーブルを含む MySQL データディレクトリへのアクセスを管理します。データディレクトリは、ログファイルおよびステータスファイルなど、その他の情報のデフォルトの場所でもあります。
Docker コンテナ(dbコンテナ)起動時のログの確認
- ログ(抜粋)
2022-02-17 10:08:54+09:00 [Note] [Entrypoint]: Database files initialized
2022-02-17 10:08:54+09:00 [Note] [Entrypoint]: Starting temporary server
2022-02-17 10:08:54+09:00 [Note] [Entrypoint]: Waiting for server startup
2022-02-17 10:08:55+09:00 [Note] [Entrypoint]: Temporary server started.
2022-02-17 10:08:59+09:00 [Note] [Entrypoint]: Creating database sample_app
2022-02-17 10:08:59+09:00 [Note] [Entrypoint]: Creating user db_user
2022-02-17 10:08:59+09:00 [Note] [Entrypoint]: Giving user db_user access to schema sample_app
2022-02-17 10:08:59+09:00 [Note] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/01_products.sql
2022-02-17 10:08:59+09:00 [Note] [Entrypoint]: Stopping temporary server
2022-02-17 10:09:01+09:00 [Note] [Entrypoint]: Temporary server stopped
2022-02-17 10:09:01+09:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.