假设我已经取消了正式的mysql:5.6.21图像.
我通过创建几个docker容器来部署此映像.
这些容器已运行一段时间,直到MySQL 5.6.22发布.mysql的官方形象:5.6使用新版本更新,但我的容器仍然运行5.6.21.
如何将图像中的更改(即升级MySQL发行版)传播到我现有的所有容器?Docker的正确方法是什么?
仅仅是为了提供更通用(而不是特定于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会通过停止并重新创建容器(保留已安装的卷)来获取更改.要防止Compose选择更改,请使用--no-recreate标志.
数据管理方面也由docker-compose通过已安装的外部"卷"(请参阅https://docs.docker.com/compose/compose-file/#volumes)或数据容器来涵盖.
这留下了潜在的向后兼容性和数据迁移问题,但这些是"应用"问题,而不是特定于Docker的问题,必须根据发行说明和测试进行检查......
我不喜欢将卷安装为主机目录的链接,因此我提出了一种模式,用于升级具有完全docker托管容器的docker容器.创建一个新的docker容器--volumes-from <container>
将为新容器提供更新的映像,共享docker managed卷的所有权.
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容器轻松恢复之前的工作方式.
考虑这个答案:
数据库名称是 app_schema
容器名称是 app_db
root密码是 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映像,重新创建并使用新映像启动容器.
我想补充一点,如果您想自动执行此过程(下载,停止并重新启动具有@Yaroslav所述相同设置的新容器),您可以使用WatchTower.一个程序,在更改容器时自动更新容器https://github.com/v2tec/watchtower
类似的答案如上
docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
以下是docker-compose
构建自定义时的外观Dockerfile
.
首先构建自定义Dockerfile,附加下一个版本号以区分.例如:docker build -t imagename:version .
这将在本地存储您的新版本.
跑 docker-compose down
编辑docker-compose.yml
文件以反映您在步骤1中设置的新图像名称.
跑docker-compose up -d
.它将在本地查找图像并使用升级后的图像.
-编辑-
我上面的步骤比他们需要的更冗长.我通过将build: .
参数包含到我的docker-compose文件中来优化我的工作流程.这些步骤现在看起来:
验证我的Dockerfile是我想要的样子.
在我的docker-compose文件中设置我的图像名称的版本号.
如果我的图像尚未构建:运行 docker-compose build
跑 docker-compose up -d
我当时没有意识到,但是docker-compose足够聪明,可以使用one命令将我的容器更新为新映像,而不必先将其删除.
在评估答案并研究我想总结的主题之后.
Docker升级容器的方式似乎如下:
应用容器不应存储应用程序数据.这样,您可以通过执行以下操作随时将app容器替换为其较新版本:
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升级)被认为是反模式.应用程序容器应该是不可变的,这应该保证可重现的行为.一些官方应用程序映像(特别是mysql:5.6)甚至没有设计为自我更新(apt-get升级不起作用).
我要感谢所有给出答案的人,所以我们可以看到所有不同的方法.