【Docker】【MySQL】在容器启动时执行SQL的方法和机制
最初先生
每次启动容器后都要执行SQL真是麻烦啊。所以,我查了一下在Docker启动时自动执行SQL的方法。
方式
目录结构如下。init.sql是在容器启动时要执行的SQL文件。
workspace
├── docker-compose.yml
└── init
└── init.sql
create database initDB;
通过docker-compose.yml文件,将主机PC的./init和容器的/docker-entrypoint-initdb.d两个目录进行绑定挂载,从而实现共享。
这样,在容器启动时会在/docker-entrypoint-initdb.d中创建init.sql文件。
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。
查看数据库列表,可以看到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-entrypoint.sh的shell脚本,该脚本在docker首次启动时被调用。
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_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://qiita.com/michikun06/items/24e99618dc59807b98c8