Mor*_*sen 19 mysql database docker
我想创建一个已填充数据的MySQL Docker镜像.
我想创建这样的3层:
|---------------------|---------------------|
Layer 3 | Customer 1 Database | Customer 2 Database |
|---------------------|---------------------|
Layer 2 | Database image with tables but no data |
|-------------------------------------------|
Layer 1 | mysql:5.6.26 |
|-------------------------------------------|
Run Code Online (Sandbox Code Playgroud)
我现在的问题是如何为第2层和第3层创建正确的Dockerfile?我的empty_with_tables.sql文件被加载到第2层,customer1.sql和customer2.sql被加载到第3层的两个图像中.我读了一些关于将SQL文件放入'/docker-entrypoint-initdb.d'的内容.但这会导致数据在第一次启动图像时出现.这不是我想要的.我希望数据在图像中准备就绪(例如,在测试中可以快速获得).
我可以启动mysql映像,从命令行加载数据并执行'commit'但这不可重现,需要在SQL文件中的数据更改时再次执行此操作.
如何才能做到这一点?
最好的祝福,
Meg*_*ubs 18
本周我遇到了同样的问题.我找到了一个无需工作的解决方案--volumes-from
已经说过的问题/var/lib/mysql
是卷,并且由于Docker UNVOLUME
在不久的将来不会支持它的Dockerfile,如果你想在默认情况下从空数据库开始,就不能将这个位置用于数据库存储.(https://github.com/docker/docker/issues/18287).这就是我覆盖的原因etc/mysqld.my.cnf
,给mysql一个新的datadir.
与pwes的回答一起,你可以像这样创建一个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
Run Code Online (Sandbox Code Playgroud)
唯一的变化是my.cnf
datadir的位置:
....
[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
....
Run Code Online (Sandbox Code Playgroud)
这不能以你想要的方式干净地完成,至少在基于官方mysql
图像时,因为你需要与服务器通信以导入数据,并且服务器不运行和初始化(从mysql的docker-entrypoint.sh
),直到容器运行,仅在图像已经构建时.
不那么干净的方法是使用/entrypoint.sh
mysql映像中的脚本在容器中运行进程,但是你必须处理入口点所需的所有设置(比如$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
Run Code Online (Sandbox Code Playgroud)
是一种导致预先初始化数据库的hackish方式,但是......它不起作用.原因是它/var/lib/mysql
在mysql的Dockerfile 中被声明为一个卷,并且在构建过程完成后,在构建过程中对该目录的任何更改都将丢失.这可以在以下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
Run Code Online (Sandbox Code Playgroud)
所以我建议docker commit
按照你描述的方式进行.最终结果与您想要实现的结果相同,但第2层可能除外.
更新:如下面的OP所述,提交也不包含卷.因此,唯一的方法似乎是编辑MySQL Dockerfile并删除VOLUME
以将数据保存在容器内,或者从容器中单独管理卷.
基于MegaWubs的答案,我发现此Dockerfile就足够了。
FROM mysql:5.6
RUN sed -i 's|/var/lib/mysql|/var/lib/mysql2|g' /etc/mysql/my.cnf
Run Code Online (Sandbox Code Playgroud)
MegaWubs 的回答很好,除了这个“sleep 30”迫使你猜测 initdb 的执行时间。为了避免这种情况,我在 /docker-entrypoint-initdb.d 中放置了一个小的 shell 脚本,在其他脚本之后执行:
/docker-entrypoint-initdb.d/
|- 01_my_data1.sql
|- 02_my_data2.sql
...
|- 99_last_processed_file.sh
Run Code Online (Sandbox Code Playgroud)
与99_last_processed_file.sh
:
#!/usr/bin/env bash
touch /tmp/server_can_shutdown.txt
Run Code Online (Sandbox Code Playgroud)
——
同时,在 Dockerfile 中,我运行另一个脚本来代替 Mortenn 的 "sleep && killall" :
# Dockerfile
# ...
COPY wait_then_shutdown.sh /tmp/wait_then_shutdown.sh
RUN /entrypoint.sh mysqld & /tmp/wait_then_shutdown.sh # <--
RUN rm /docker-entrypoint-initdb.d/*
Run Code Online (Sandbox Code Playgroud)
与wait_then_shutdown.sh
:
#!/usr/bin/env bash
while [ ! -f /tmp/server_can_shutdown.txt ] # <-- created by 99_last_processed_file.sh
do
sleep 2
done
kill $(pidof mysqld)
Run Code Online (Sandbox Code Playgroud)
——
现在,mysqld
仅在 /docker-entrypoint-initdb.d 中处理所有其他文件时停止
Mor*_*sen -3
因此,我对这个问题的解决方案只是不将所有内容分层,而是创建一个基础映像并使用 --volumes-from 从纯数据容器注入数据库文件。
归档时间: |
|
查看次数: |
15113 次 |
最近记录: |