Docker 提交 - 未保存数据库更改
Posted
技术标签:
【中文标题】Docker 提交 - 未保存数据库更改【英文标题】:Docker commit - DB changes are no saved 【发布时间】:2019-01-31 00:23:32 【问题描述】:我安装了最新的 Docker CS,从 Docker Hub 获得了LAMP image。我正在尝试在其中创建一个数据库并使用保存在其中的数据库制作一个新图像。
-
启动容器:
docker run --name mycontainer fauria/lamp
这将启动基于 Ubuntu 的容器并启动 Apache 服务器。 mysql 服务器也在容器中运行。
访问容器外壳:docker exec -i -t mycontainer bash
创建一个数据库并在其上运行一些 MySQL 命令:
mysql -u root
CREATE DATABASE mydbname;
USE mydbname;
CREATE FUNCTION ...
...
停止容器:docker stop mycontainer
创建镜像:docker commit
docker ps -l -qmynickname/appname:v1
移除容器docker container rm mycontainer
现在我预计,如果我基于新图像运行容器,我已经拥有数据库。但它不存在。
docker run --name mycontainer --rm -p 80:80 -e LOG_STDOUT=true -e LOG_STDERR=true -e LOG_LEVEL=debug -v /home/username/dev/appname/www:/var/www/html mynickname/appname:v1
我错过了什么?
【问题讨论】:
docker commit
不会将数据保存在外部卷中,这可能是您的图像具有的。不过,我建议通读 Docker 的 official tutorial and building and running custom images:IME 所有一体式容器、在正在运行的容器上运行交互式命令或使用 docker commit
都不是最佳实践。
@DavidMaze OP 提供了完整的docker run
命令行。数据库没有外部卷,只有 html 文件。
【参考方案1】:
原因是/var/lib/mysql
在 Dockerfile 中被列为 VOLUME
。
您所做的更改将保留在 docker stop <yourcontainer>
和 docker start <yourcontainer>
命令之间。但是当你提交一个容器时,Dockerfile 中标记为VOLUME
的每个目录都会被替换为其原始内容。 (即使您没有将外部卷挂载到该目录也会发生这种情况。)请参阅docker commit。
您可以通过在VOLUME
目录之外的某处进行更改来轻松检查您的其他更改是否保留在提交中。例如,在容器内运行 date>/mydate
然后提交它。然后,当您从该映像运行新容器时,/mydate
文件仍将存在。
如果您想保留数据库更改,您可以通过克隆 repo 来实现,然后从 Dockerfile 中删除行 VOLUME /var/lib/mysql
。如果您随后构建新映像并运行它,它会在您提交容器时保留您的数据库更改。
通常,在生产环境中,您将数据库文件挂载到数据容器或主机上。这样,如果您提交容器,数据库数据将保留在数据容器或主机上。
【讨论】:
【参考方案2】:这不是数据库通过容器工作的方式。您必须将数据持久保存在主机上才能保留它。容器是一次性的,它们来来去去。
我建议您通过卷将数据库相关数据保存在主机上。如果该容器崩溃,下一个容器应该保留该容器的服务并保留数据。
例如:-
在官方mysql示例中
$ docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
你可以看到他们正在挂载一个卷来持久化数据并在容器重新启动时保留。
干杯!
【讨论】:
【参考方案3】:将数据与图像一起提交是一个有用的测试场景。使用预制基础映像时,您可能必须删除 VOLUME 条目,但请参阅docker-copyedit。
【讨论】:
你是英雄!非常感谢你提供这个工具。当我尝试使用提交的容器构建测试用例时,我遇到了完全相同的情况。首先由于已知原因它没有成功,然后你的工具拯救了我的一天:)【参考方案4】:在我的例子中,我通过将数据库转储到 SQL 文件来保存数据库架构更改。我要做的是:
-
我创建了一个简单的 bash 脚本,将 DB 转储到 /docker-entrypoint-initdb.d/dump.sql 作为初始化。
#!/bin/bash
mysqldump -u root cepheid_development --single-transaction --quick --lock-tables=false > /docker-entrypoint-initdb.d/dump.sql
-
我将脚本复制到我的 Dockerfile 中的容器中:
COPY docker_resources/dump_db.sh /tmp
-
我从容器外部自动运行我的脚本(命令行或其他脚本):
docker exec $container_id /tmp/dump_db.sh
【讨论】:
以上是关于Docker 提交 - 未保存数据库更改的主要内容,如果未能解决你的问题,请参考以下文章