如何在映像更改后升级docker容器

Yar*_*hiy 481 docker

假设我已经取消了正式的mysql:5.6.21图像.

我通过创建几个docker容器来部署此映像.

这些容器已运行一段时间,直到MySQL 5.6.22发布.mysql的官方形象:5.6使用新版本更新,但我的容器仍然运行5.6.21.

如何将图像中的更改(即升级MySQL发行版)传播到我现有的所有容器?Docker的正确方法是什么?

Yar*_*hiy 541

在评估答案并研究我想总结的主题之后.

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
Run Code Online (Sandbox Code Playgroud)

您可以将数据存储在主机(作为卷安装的目录中)或特殊的仅数据容器中.在这里,这里这里阅读更多相关信息.

在容器内升级应用程序(例如,使用yum/apt-get升级)被认为是反模式.应用程序容器应该是不可变的,这应该保证可重现的行为.一些官方应用程序映像(特别是mysql:5.6)甚至没有设计为自我更新(apt-get升级不起作用).

我要感谢所有给出答案的人,所以我们可以看到所有不同的方法.

  • 如果需要数据迁移怎么办?新服务器无法装入数据,因为它是旧格式,需要知道正在进行迁移并更改数据表示. (28认同)
  • 我认为,图像设计者应该考虑到这一点,并允许在容器首次运行期间启动自定义(例如,数据迁移)命令. (10认同)
  • 如何恢复用于创建容器的命令?我不记得我通过的所有选项。 (5认同)
  • @DorRotman当我检查时,该URL无法正常工作,但这个URL确实有效:https://intercityup.com/blog/running-upgrading-mysql-server-docker.html (4认同)
  • @static_rtti在创建新的之前,[`docker rename my-mysql-container trash-container`](https://docs.docker.com/engine/reference/commandline/rename/)怎么样? (4认同)
  • 相关文章:https://intercityup.com/blog/running-upgrading-mysql-server-docker/ (2认同)
  • 是否有任何一体化命令来更新容器而不必手动停止,删除它,并再次创建它(基于已拉出的新图像)? (2认同)

kMa*_*ith 78

我不喜欢将卷安装为主机目录的链接,因此我提出了一种模式,用于升级具有完全docker托管容器的docker容器.创建一个新的docker容器--volumes-from <container>将为新容器提供更新的映像,共享docker managed卷的所有权.

docker pull mysql
docker create --volumes-from my_mysql_container [...] --name my_mysql_container_tmp mysql
Run Code Online (Sandbox Code Playgroud)

my_mysql_container如果升级的容器没有正确的数据,或者未通过完整性测试,则无法立即删除原始文件,您可以恢复到已知的工作容器.

此时,我通常会为容器运行任何备份脚本,以便在出现问题时给自己一个安全网

docker stop my_mysql_container
docker start my_mysql_container_tmp
Run Code Online (Sandbox Code Playgroud)

现在,您有机会确保您希望在新容器中的数据存在并进行健全性检查.

docker rm my_mysql_container
docker rename my_mysql_container_tmp my_mysql_container
Run Code Online (Sandbox Code Playgroud)

只要任何容器正在使用它们,docker卷就会粘在一起,因此您可以安全地删除原始容器.删除原始容器后,新容器可以采用原始容器的名称,以使一切尽可能美观.

使用此模式升级docker容器有两个主要优点.首先,它允许将卷直接传输到升级的容器,从而无需将卷安装到主机目录.其次,你永远不会处于没有工作泊坞容器的位置; 因此,如果升级失败,您可以通过再次旋转原始docker容器轻松恢复之前的工作方式.

  • @KajMagnus我经常使用docker swarms,我喜欢写我的容器以便在群中工作.当我在一个swarm中旋转一个容器时,我不知道容器将依赖哪个swarm节点,所以我不能依赖包含我想要的数据的主机路径.由于Docker 1.9(我认为)卷可以在主机之间共享,这使得使用我所描述的方法轻松升级和迁移容器.另一种方法是确保在所有群集节点上安装一些网络卷,但这听起来像是一个巨大的痛苦. (4认同)
  • 为什么不喜欢在Docker容器中装载主机卷?(我正是这样做的,所以我对反对这样做的论据感兴趣: - )我已经安装了例如:`./postgres-data /:/ var/lib/postgres/data` - 即安装主机目录` ./ postgres-data /`,在我的PostgreSQL容器中.) (3认同)

Ron*_*las 26

仅仅是为了提供更通用(而不是特定于mysql)的答案......

  1. 简而言之

与服务映像注册表同步(https://docs.docker.com/compose/compose-file/#image):

docker-compose pull 
Run Code Online (Sandbox Code Playgroud)

如果docker-compose文件或图像已更改,请重新创建容器:

docker-compose up -d
Run Code Online (Sandbox Code Playgroud)
  1. 背景

容器映像管理是使用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的问题,必须根据发行说明和测试进行检查......


Ric*_*olo 23

我想补充一点,如果您想自动执行此过程(下载,停止并重新启动具有@Yaroslav所述相同设置的新容器),您可以使用WatchTower.一个程序,在更改容器时自动更新容器https://github.com/v2tec/watchtower


Ale*_*rri 20

考虑这个答案:

  • 数据库名称是 app_schema
  • 容器名称是 app_db
  • root密码是 root123

如何在容器内存储应用程序数据时更新MySQL

这被认为是一种不好的做法,因为如果丢失容器,您将丢失数据.虽然这是一个不好的做法,但这是一种可行的方法:

1)将数据库转储作为SQL:

docker exec app_db sh -c 'exec mysqldump app_schema -uroot -proot123' > database_dump.sql
Run Code Online (Sandbox Code Playgroud)

2)更新图像:

docker pull mysql:5.6
Run Code Online (Sandbox Code Playgroud)

3)更新容器:

docker rm -f app_db
docker run --name app_db --restart unless-stopped \
-e MYSQL_ROOT_PASSWORD=root123 \
-d mysql:5.6
Run Code Online (Sandbox Code Playgroud)

4)恢复数据库转储:

docker exec app_db sh -c 'exec mysql -uroot -proot123' < database_dump.sql
Run Code Online (Sandbox Code Playgroud)

如何使用外部卷更新MySQL容器

使用外部卷是一种更好的数据管理方式,更容易更新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
Run Code Online (Sandbox Code Playgroud)

2)更新MySQL(与文件相同的文件夹docker-compose.yml):

docker-compose pull
docker-compose up -d
Run Code Online (Sandbox Code Playgroud)

注意:上面的最后一个命令将更新MySQL映像,重新创建并使用新映像启动容器.


Edd*_*ude 14

类似的答案如上

docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这不会更新现有的容器.这将只更新拉出的图像,但现有容器是不可变的,仍然使用用于创建它的原始图像.这仅适用于从图像创建新容器,但任何现有容器仍基于原始图像. (5认同)

gdb*_*dbj 11

以下是docker-compose构建自定义时的外观Dockerfile.

  1. 首先构建自定义Dockerfile,附加下一个版本号以区分.例如:docker build -t imagename:version . 这将在本地存储您的新版本.
  2. docker-compose down
  3. 编辑docker-compose.yml文件以反映您在步骤1中设置的新图像名称.
  4. docker-compose up -d.它将在本地查找图像并使用升级后的图像.

-编辑-

我上面的步骤比他们需要的更冗长.我通过将build: .参数包含到我的docker-compose文件中来优化我的工作流程.这些步骤现在看起来:

  1. 验证我的Dockerfile是我想要的样子.
  2. 在我的docker-compose文件中设置我的图像名称的版本号.
  3. 如果我的图像尚未构建:运行 docker-compose build
  4. docker-compose up -d

我当时没有意识到,但是docker-compose足够聪明,可以使用one命令将我的容器更新为新映像,而不必先将其删除.

  • 所以你说这是因为我的解决方案不是自动化的,它无效?这是OP的要求吗?其他答案是否意味着自动化?真的很困惑.并且,我认为这些投票对来到这里的其他人来说是一种伤害.我的回答是100%有效的问题. (7认同)

ber*_*uic 8

如果你不想使用 Docker Compose,我可以推荐portainer。它具有重新创建功能,可让您在拉取最新镜像的同时重新创建容器。


sea*_*mcl 2

您需要重建所有映像并重新启动所有容器,或者以某种方式更新软件并重新启动数据库。没有升级路径,只能由您自己设计。