如何在构build时创build已填充的MySQL Docker镜像

我想创build一个已经填充数据的MySQL Docker镜像。

我想创build这样的3层:

|---------------------|---------------------| Layer 3 | Customer 1 Database | Customer 2 Database | |---------------------|---------------------| Layer 2 | Database image with tables but no data | |-------------------------------------------| Layer 1 | mysql:5.6.26 | |-------------------------------------------| 

我的问题是现在如何为第2层和第3层创build一个正确的Dockerfile? 其中我的empty_with_tables.sql文件被加载到第2层,customer1.sql和customer2.sql被加载到第3层的两个图像中。我读了一些关于将SQL文件放入“/docker-entrypoint-initdb.d”的内容。 但这会导致图像首次启动时的数据。 这不是我想要的。 我希望数据在图像中准备好(例如在testing中快速提供)。

我可以启动mysql映像,从命令行加载数据并执行“提交”,但这不是可重复的,需要在SQL文件中的数据更改时重新执行。

如何才能做到这一点?

最好的祝福,

  • 莫滕格林赫尔曼森

我本周遇到了同样的问题。 我find了一个不需要--volumes-from的工作解决scheme

已经说过的问题是/var/lib/mysql是一个卷,由于Docker在不久的将来将不支持UNVOLUME中的UNVOLUME,所以如果你想启动,你不能使用这个位置来存储你的数据库在默认情况下closures一个空的数据库。 ( https://github.com/docker/docker/issues/18287 )。 这就是为什么我覆盖etc/mysqld.my.cnf ,给MySQL一个新的datadir。

再加上pwes的回答,你可以像这样创build一个Dockerile:

 FROM mysql:5.6 ENV MYSQL_DATABASE db ENV MYSQL_ROOT_PASSWORD pass COPY db.sql /docker-entrypoint-initdb.d/db.sql COPY my.cnf /etc/mysql/my.cnf RUN /entrypoint.sh mysqld & sleep 30 && killall mysqld RUN rm /docker-entrypoint-initdb.d/db.sql 

my.cnf唯一的变化是数据库的位置:

 .... [mysqld] skip-host-cache skip-name-resolve user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 basedir = /usr datadir = /var/lib/mysql2 <-- can be anything except /var/lib/mysql tmpdir = /tmp lc-messages-dir = /usr/share/mysql explicit_defaults_for_timestamp .... 

这不能干净地完成你想要的方式,至less当基于官方的mysql镜像,因为你需要与服务器通信导入数据和服务器不运行和初始化(从mysql的docker-entrypoint.sh )直到容器运行,这是只有当图像已经build立。

不太干净的方法是使用mysql image中的/entrypoint.sh脚本在容器中运行进程,但必须注意入口点所需的所有设置(如$MYSQL_ROOT_PASSWORD )以及清理在导入数据之后立即停止守护进程。 就像是:

 FROM mysql:5.6 ADD data.sql /docker-entrypoint-initdb.d/00-import-data.sql ENV MYSQL_ROOT_PASSWORD somepassword ENV MYSQL_DATABASE db1 RUN /entrypoint.sh mysqld & sleep 30 && killall mysqld 

是一个hackish的方式,导致预初始化数据库,但是…它不工作。 原因是/var/lib/mysql在mysql的Dockerfile中被声明为一个卷,并且在构build过程中对这个目录所做的任何更改在构build步骤完成后都会丢失。 这可以在下面的Dockerfile中看到:

 FROM mysql:5.6 RUN touch /var/lib/mysql/some-file && ls /var/lib/mysql RUN touch /var/lib/mysql/some-file2 && ls /var/lib/mysql 

所以我build议你用docker commit方式进行描述。 最终的结果与你想要达到的结果是一样的,除了第2层以外。

更新 :由于OP评论下面,提交也不包含卷。 所以,唯一的办法似乎是编辑MySQL Dockerfile并删除VOLUME来保存容器中的数据,或者独立于容器来pipe理卷。

build立在MegaWubs的答案,我发现这个Dockerfile是足够的。

 FROM mysql:5.6 RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf 

所以我对这个问题的解决scheme只是不分层的一切,而是创build一个基本的图像,并使用–volumes-from从数据专用容器注入数据库文件。