使用 Docker 镜像mysql:5.7.21
我想创建一个基于它的新镜像,该镜像已经初始化了它的数据库。(我想将其用于我的接受环境)。
我知道/docker-entrypoint-initdb.d
,我可以休耕:
FROM mysql:5.7.21
COPY ./init /docker-entrypoint-initdb.d
但问题是它只会复制 tar/sql 文件,但在第一次运行之前不会执行。另一个缺点也是图像大小。例如,如果您在容器内复制 200MB 的数据,那么这些文件将保留在图像中(作为图层)。
所以我想知道是否有我没有想到的多阶段或新的 --squash 标志的组合(这将启用、添加文件、执行文件、删除文件)。
在我搜索这个问题的过程中,我还发现了--datadir
标志。不知道这有什么帮助。
编辑:
到目前为止,我有休耕:
FROM mysql:5.7.21 as builder
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
ENV MYSQL_DATABASE example
COPY ./init /docker-entrypoint-initdb.d
RUN head -n-2 < /usr/local/bin/docker-entrypoint.sh > /usr/local/bin/docker-entrypoint.sh
&& docker-entrypoint.sh mysqld
&& /etc/init.d/mysql start
&& mysql -uroot -e 'FLUSH TABLES;'
&& mysql -uroot -e 'show tables;' mysql
&& mysql -uroot -e 'show tables;' example
&& /etc/init.d/mysql stop
# This shows the files!
&& ls -la /var/lib/mysql
# This shows no files?!!
RUN ls -la /var/lib/mysql
FROM mysql:5.7.21
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
ENV MYSQL_DATABASE example
COPY --from=builder /var/lib/mysql /var/lib/mysql
RUN ls -la
RUN ls -la /var/lib/mysql
&& /etc/init.d/mysql start
&& mysql -uroot -e 'show tables;' mysql
&& mysql -uroot -e 'show tables;' example
请参阅上面的内联评论...发生了一些非常奇怪的事情?因此,在同一个 RUN 中,当我对/var/lib/mysql
执行ls -la
时,我可以看到文件。但是在新层(新运行)中它是空的:S
所以我找到了解决方案!!我的问题在于/var/lib/mysql 是一个卷:https://github.com/docker-library/mysql/blob/ad625c64a06e16683e997e5a0147508d115f4989/5.7/Dockerfile#L71
一个工作的多级 Dockerfile:
FROM mysql:5.7.21 as builder
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
ENV MYSQL_DATABASE example
COPY ./init /docker-entrypoint-initdb.d
RUN head -n-2 < /usr/local/bin/docker-entrypoint.sh > /usr/local/bin/docker-entrypoint.sh
RUN mkdir -p /var/lib/mysql_tmp
RUN docker-entrypoint.sh mysqld --datadir /var/lib/mysql_tmp
FROM mysql:5.7.21
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
ENV MYSQL_DATABASE example
COPY --from=builder /var/lib/mysql_tmp /var/lib/mysql_tmp
CMD ["mysqld", "--datadir", "/var/lib/mysql_tmp"]
所以我们在这里做的是确保删除最后 2 行(可以更改为只删除最后一行),因为它包含exec "$@"
这基本上意味着exec msqld
.那是MySQL守护进程,所以它会卡在那里。
此外,我将 datadir 从var/lib/mysql
(这是一个卷)更改为var/lib/mysql_tmp
(因为没有更好的名称)。
在最后阶段,我复制var/lib/mysql_tmp
并确保 mysqld 使用该目录。
现在我可以烘烤(对我来说只读)db 用于我的验收环境。
如果检查 Dockerfile 中是否有mysql:5.7.21
映像 (https://hub.docker.com/r/library/mysql/),您将看到入口点设置为["docker-entrypoint.sh"]
,因此这是运行映像时执行的第一个命令。
如果你想在映像创建期间执行它(因此,使映像大小很大,但没关系),你只需要把它放在你的Dockerfile中:
RUN docker-entrypoint.sh /bin/true
此入口点将执行在/docker-entrypoint-initdb.d
中找到的脚本,但正如您所指出的,脚本也会占用空间。为了丢弃文件,您可以使用多阶段构建来仅复制原始数据库。
再次检查 Dockerfile,查看映像中唯一的卷是/var/lib/mysql
。这应该是包含数据库上所有信息的目录,它应该是您复制的内容。结果是这样的:
FROM mysql:5.7.21 as base
COPY ./init /docker-entrypoint-initdb.d
RUN docker-entrypoint.sh /bin/true
FROM mysql:5.7.21
COPY --from=base /var/lib/mysql /var/lib/mysql
综上所述,我不建议创建"初始化"图像,因为这有点违背使用容器的精神,但这是另一个问题;)