2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Docker】【MySQL】コンテナ起動時にSQLを実行する方法とその仕組み

Posted at

初めに

コンテナ起動後、毎回SQLを実行するのめんどくさいですよね。
ということで、Docker起動時に自動でSQLを実行してくれる方法を調べました。

やり方

ディレクトリ構成は以下です。
init.sqlがコンテナ起動時に実行したいSQLファイルになります。

workspace
├── docker-compose.yml
└── init
    └── init.sql
init.sql
create database initDB;                               

docker-compose.ymlにて、ホストPCの./initと、コンテナの/docker-entrypoint-initdb.dの二つを共有させるようにバインドマウントさせます。
これにより、コンテナ起動時に/docker-entrypoint-initdb.dの中にinit.sql作成されます。

docker-compose.yml
version: '3'
services:
  mysql:
    image: mysql:latest
    container_name: my-mysql-container
    environment:
      MYSQL_ROOT_PASSWORD: your-root-password
      MYSQL_DATABASE: your-database-name
      MYSQL_USER: your-username
      MYSQL_PASSWORD: your-password
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d <- 追加
volumes:
  mysql-data:

これで準備完了です。
docker compose up -dでコンテナを作成します。

$ docker compose up -d
[+] Running 3/3
 ✔ Network mysqltest_default      Created                                                                          0.0s
 ✔ Volume "mysqltest_mysql-data"  Created                                                                          0.0s
 ✔ Container my-mysql-container   Started                                                                          0.0s
$

docker execでコンテナの中に入ってMySQLにログインします。
DBの一覧を見ると、init.sqlで定義したSQLが実行されていることがわかります。

$ docker exec -it my-mysql-container bash
bash-4.4#
bash-4.4#
bash-4.4# mysql -u root -p
Enter password:

mysql>
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| initDB             | <- init.sqlで作成されたデータベース
| mysql              |
| performance_schema |
| sys                |
| your-database-name |
+--------------------+
6 rows in set (0.01 sec)

初回実行される仕組み

dockerイメージには、docker初回起動時に呼び出されるdocker-entrypoint.shというシェルスクリプトが定義されています。
MySQLのdocker-entrypoint.shには/docker-entrypoint-initdb.dの内のsqlファイルを実行するという処理が書いてあるようです。

MySQL 8.0のdocker-entrypoint.shは以下。
https://github.com/docker-library/mysql/blob/master/8.0/docker-entrypoint.sh

疑問点

sqlファイル以外は実行できないの?

結論:SQLファイルとshファイルが実行可能
docker-entrypoint.shには以下のようなソースがあります。

docker-entrypoint.sh
docker_process_init_files() {
	# mysql here for backwards compatibility "${mysql[@]}"
	mysql=( docker_process_sql )

	echo
	local f
	for f; do
		case "$f" in
			*.sh)
				# https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
				# https://github.com/docker-library/postgres/pull/452
				if [ -x "$f" ]; then
					mysql_note "$0: running $f"
					"$f"
				else
					mysql_note "$0: sourcing $f"
					. "$f"
				fi
				;;
			*.sql)     mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
			*.sql.bz2) mysql_note "$0: running $f"; bunzip2 -c "$f" | docker_process_sql; echo ;;
			*.sql.gz)  mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
			*.sql.xz)  mysql_note "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;;
			*.sql.zst) mysql_note "$0: running $f"; zstd -dc "$f" | docker_process_sql; echo ;;
			*)         mysql_warn "$0: ignoring $f" ;;
		esac
		echo
	done
}

このソースによると、shファイルとsqlファイルの場合は実行、sqlファイルの圧縮ファイルであれば解凍してから実行しているようです。このため、shファイルとsqlファイルであれば実行可能になります。

複数ファイルがある場合はどれから実行されるの?

結論:ファイル名の昇順で実行される
docker-entrypoint-initdb.dにあるファイルは名前の昇順で実行されます。
依存関係のあるファイルを実行させる場合、ファイル名の頭に数字をつけるなどして工夫することが必要がありそうです。

$ ls
1_init.sql  2_init.sql  3_init.sql  

最後に

今回はコンテナ起動時にファイルを実行する方法を紹介しました。
便利なのでぜひ試してみてください。

参考

https://qiita.com/moaikids/items/f7c0db2c98425094ef10
https://zenn.dev/re24_1986/articles/978801ae092498
https://kakakakakku.hatenablog.com/entry/2017/11/08/193031
https://qiita.com/michikun06/items/24e99618dc59807b98c8

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?