假设我已经拉取了官方的mysql:5.6.21镜像。
我通过创建多个Docker容器来部署此镜像。
这些容器已经运行了一段时间,直到MySQL 5.6.22发布。官方的mysql:5.6镜像已更新为新版本,但我的容器仍在运行5.6.21。
我如何将镜像中的更改(即升级MySQL发行版)传播到所有现有的容器中?这是使用Docker的正确方法吗?
假设我已经拉取了官方的mysql:5.6.21镜像。
我通过创建多个Docker容器来部署此镜像。
这些容器已经运行了一段时间,直到MySQL 5.6.22发布。官方的mysql:5.6镜像已更新为新版本,但我的容器仍在运行5.6.21。
我如何将镜像中的更改(即升级MySQL发行版)传播到所有现有的容器中?这是使用Docker的正确方法吗?
在评估答案并研究该主题后,我想做个总结。
Docker 升级容器的方式似乎是这样的:
应用程序容器不应存储应用程序数据。这样,您可以通过执行以下命令随时用其新版本替换应用程序容器:
docker pull mysql
docker stop my-mysql-container
docker rm my-mysql-container
docker run --name=my-mysql-container --restart=always \
-e MYSQL_ROOT_PASSWORD=mypwd -v /my/data/dir:/var/lib/mysql -d mysql
您可以将数据存储在主机上(作为挂载的目录)或特殊的仅数据容器中。了解更多信息请参见:
在容器内升级应用程序(例如使用yum/apt-get upgrade)被认为是反模式。应用程序容器应该是不可变的,这可以保证可复现性。一些官方应用程序镜像(特别是mysql:5.6)甚至没有设计自我更新(apt-get upgrade不起作用)。
感谢所有提供答案的人,这样我们就可以看到各种不同的方法。
我不喜欢将卷挂载为主机目录的链接,因此我想出了一种方法来使用完全由Docker管理的容器来升级Docker容器。使用 --volumes-from <container>
创建一个新的Docker容器,可以使更新后的镜像与Docker管理的卷共享所有权。
docker pull mysql
docker create --volumes-from my_mysql_container [...] --name my_mysql_container_tmp mysql
如果不立即删除原始的 my_mysql_container
,则可以在升级后容器没有正确的数据或未通过健全性测试时,还原到已知工作的容器。
此时,我通常会运行针对该容器的任何备份脚本,以便在出现问题时给自己提供安全保障。
docker stop my_mysql_container
docker start my_mysql_container_tmp
现在你有机会确认新容器中应该存在的数据,并运行一次健全性检查。
docker rm my_mysql_container
docker rename my_mysql_container_tmp my_mysql_container
只要有任何容器在使用,Docker卷就会一直存在,因此您可以安全地删除原始容器。一旦删除原始容器,新容器就可以承担原始容器的名称,使一切恢复原状。
使用此模式升级Docker容器有两个主要优点。首先,它通过允许将卷直接转移给升级后的容器而消除了需要挂载到主机目录的需求。其次,您永远不会处于没有工作的Docker容器的位置;因此,如果升级失败,您可以轻松地通过重新启动原始Docker容器来恢复之前的工作状态。
./postgres-data/:/var/lib/postgres/data
- 也就是在我的PostgreSQL容器内挂载了主机目录./postgres-data/
。) - KajMagnus仅为提供一个更加通用的(不针对MySQL特定的)答案...
与服务镜像库同步(https://docs.docker.com/compose/compose-file/#image):
docker-compose pull
如果 Docker Compose 文件或镜像已更改,则重新创建容器:
docker-compose up -d
容器镜像管理是使用docker-compose的原因之一(参见https://docs.docker.com/compose/reference/up/)。
如果存在服务的现有容器,并且在容器创建后更改了服务的配置或映像,则docker-compose up通过停止和重新创建容器(保留已挂载的卷)来捕获更改。要防止Compose捕获更改,请使用--no-recreate标志。
数据管理方面也通过挂载外部“卷”(请参见https://docs.docker.com/compose/compose-file/#volumes)或数据容器来使用docker-compose进行处理。
这仍然存在潜在的向后兼容性和数据迁移问题,但这些是“应用程序”问题,而不是Docker特定的问题,必须根据发布说明和测试进行检查...
我想补充一点,如果你想自动完成这个过程(下载、停止并重新启动一个新的容器,其设置与 @Yaroslav 所描述的相同),你可以使用 WatchTower。它是一个可以在容器发生改变时自动更新容器的程序。https://github.com/v2tec/watchtower
考虑以下答案:
app_schema
app_db
root123
这被认为是一种不好的做法,因为如果你失去了容器,你将失去数据。尽管这是一种不好的做法,下面是一种可能的方法:
1)将数据库导出为SQL文件:
docker exec app_db sh -c 'exec mysqldump app_schema -uroot -proot123' > database_dump.sql
2) 更新图像:
docker pull mysql:5.6
3) 更新容器:
docker rm -f app_db
docker run --name app_db --restart unless-stopped \
-e MYSQL_ROOT_PASSWORD=root123 \
-d mysql:5.6
4) 恢复数据库转储:
docker exec app_db sh -c 'exec mysql -uroot -proot123' < database_dump.sql
使用外部卷是更好的数据管理方式,也更容易更新MySQL。失去容器不会丢失任何数据。您可以使用docker-compose在单个主机上方便地管理多容器Docker应用程序:
1)创建docker-compose.yml
文件以管理您的应用程序:
version: '2'
services:
app_db:
image: mysql:5.6
restart: unless-stopped
volumes_from: app_db_data
app_db_data:
volumes: /my/data/dir:/var/lib/mysql
2) 更新 MySQL(从与 docker-compose.yml
文件相同的文件夹中):
docker-compose pull
docker-compose up -d
注意:上面的最后一个命令将更新MySQL镜像,重新创建并启动使用新镜像的容器。
docker-compose
,这个方案是否可行?https://dev59.com/wlwZ5IYBdhLWcg3wbv3q#31485685 - sivabudhdocker pull image_uri:tag && docker restart container_running_that_image
对我来说有效。不需要 docker-compose pull && docker-compose up -d
。 - Yuri Pozniak与上面类似的回答
docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
docker-compose
构建自定义Dockerfile
的示例:
docker build -t imagename:version .
,这将在本地保存您的新版本。docker-compose down
命令。docker-compose.yml
文件,以反映您在第1步设置的新映像名称。docker-compose up -d
命令。它会在本地查找镜像并使用您升级的镜像。build: .
参数来优化了我的工作流程。现在步骤如下:
docker-compose build
命令。docker-compose up -d
命令。docker-compose up -d
而不需要先停止一切。 - radicand您需要重新构建所有的镜像并重启所有的容器,或者以某种方式更新软件并重启数据库。没有升级路径,只能自己设计。
docker restart
命令,但我不确定它是否会捕捉到镜像的更改。而且我的容器内的数据会发生什么? - Yaroslav Stavnichiy确保您在容器中存储与进程状态相关的所有持久数据(配置、日志或应用数据)都使用卷。更新Dockerfile并使用所需的更改重新构建映像,然后将卷挂载到适当的位置并重新启动容器。