在用 docker 创建 mysql 容器的时,有时候我们期望容器启动后数据库和表已经自动建好,初始化数据也已自动录入,也就是说容器启动后我们就能直接连上容器中的数据库,使用其中的数据了。
其实 mysql 的官方镜像是支持这个能力的,在容器启动的时候自动执行指定的 sql 脚本或者 shell 脚本,我们一起来看看 mysql 官方镜像的 Dockerfile,如下图:
已经设定了 ENTRYPOINT,里面会调用 <font color=”red”>/entrypoint.sh</font> 这个脚本,我们把 mysql:8 这个镜像 pull 到本地,再用 docker run 启动起来,看看里面的 entrypoint.sh 这个脚本的内容,有一段内容就是从固定目录下遍历所有的.sh 和.sql 后缀的文件,然后执行,如下图:
搞清楚原理了,现在我们来实践一次吧:
在 docker 上搭建 disconf 环境时,需要搭建 mysql 数据库,并且要依次执行四个 sql 文件分别对数据库,表,数据做初始化,我们有两种做法:
- 将四个 sql 文件复制到 /docker-entrypoint-initdb.d 目录下,这样容器 run 的时候的时候就会自动执行这四个 sql,但是从截图的脚本上来看,对多个文件中的执行顺序是不能指定的,如果创建数据库的脚本晚于创建表的脚本执行,那么就会导致建表失败,所以这种复制 sql 的方式不能满足我们的需要 (不过,如果将四个文件按照顺序合成一个 sql 就能满足要求了);
- 做一个 sh 文件,在里面按我们自己的需要来执行 sql,内容如下:
#!/bin/bash
mysql -uroot -p$MYSQL_ROOT_PASSWORD <<EOF
source $WORK_PATH/$FILE_0;
source $WORK_PATH/$FILE_1;
source $WORK_PATH/$FILE_2;
source $WORK_PATH/$FILE_3;
看得出 shell 很简单,登录 mysql 并执行指定的 sql 文件,MYSQL_ROOT_PASSWORD,WORK_PATH,FILE_0 这些都是环境变量。
再来看看对应的 Dockerfile 怎么写,如下:
# Docker image of disconf mysql
# VERSION 0.0.1
# Author: bolingcavalry
#基础镜像使用 daocloud.io/library/mysql:8
FROM daocloud.io/library/mysql:8
#作者
MAINTAINER BolingCavalry <zq2599@gmail.com>
#定义工作目录
ENV WORK_PATH /usr/local/work
#定义会被容器自动执行的目录
ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
#定义 sql 文件名
ENV FILE_0 0-init_table.sql
ENV FILE_1 1-init_data.sql
ENV FILE_2 20151225.sql
ENV FILE_3 20160701.sql
#定义 shell 文件名
ENV INSTALL_DATA_SHELL install_data.sh
#创建文件夹
RUN mkdir -p $WORK_PATH
#把数据库初始化数据的文件复制到工作目录下
COPY ./$FILE_0 $WORK_PATH/
COPY ./$FILE_1 $WORK_PATH/
COPY ./$FILE_2 $WORK_PATH/
COPY ./$FILE_3 $WORK_PATH/
#把要执行的 shell 文件放到 /docker-entrypoint-initdb.d/ 目录下,容器会自动执行这个 shell
COPY ./$INSTALL_DATA_SHELL $AUTO_RUN_DIR/
#给执行文件增加可执行权限
RUN chmod a+x $AUTO_RUN_DIR/$INSTALL_DATA_SHELL
0-init_table.sql,1-init_data.sql,20151225.sql,20160701.sql 这四个文件就是我们要执行的 sql,在构造 docker 镜像的时候被复制到镜像文件中了;
完整内容请 clone 我的 github:git@github.com:zq2599/docker_disconf.git,clone 完毕后进入里面的 mysql 文件夹,在此文件夹下执行命令行 docker build -t disconf_mysql:0.0.1 . 构建镜像;
再执行 docker run –name mysqldisconf -e MYSQL_ROOT_PASSWORD=123456 -idt disconf_mysql:0.0.1 启动一个容器,再执行 docker logs -f mysqldisconf 查看容器日志,如下图红框,可以看到我们写入指定位置的 sh 文件已经被执行了:
我们去数据库里看看数据是不是真的有了,执行 docker exec -it mysqldisconf /bin/bash 进入容器;
执行 mysql -uroot -p123456 登录 mysql 后,操作如下图:
可以看到,show databases,show tables,select * from app 等操作都可以证明 sql 已经在容器创建后被自动执行,达到了我们的目的。
欢迎关注我的公众号