docker容器镜像改变后如何升级

假设我已经取出了官方的mysql: 5.6.21形象

我通过创建几个docker容器部署了这个映像。

这些容器已经运行了一段时间,直到MySQL 5.6.22发布。mysql:5.6的官方形象随着新版本的发布而更新,但我的容器仍然运行5.6.21。

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

548699 次浏览

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

这也是我为自己的照片所做的努力。我有一个服务器环境,从中创建Docker映像。当我更新服务器时,我希望所有基于Docker映像运行容器的用户都能够升级到最新的服务器。

理想情况下,我更喜欢生成一个新版本的Docker映像,并让所有基于该映像以前版本的容器自动更新到“到位”的新映像。但这种机制似乎并不存在。

因此,到目前为止,我能想到的下一个最佳设计是提供一种让容器更新自身的方法——类似于桌面应用程序检查更新并升级自身的方式。在我的例子中,这可能意味着编写一个脚本,其中包含从一个知名标记提取的Git。

图像/容器实际上并没有改变,但是容器的“内部”发生了变化。您可以想象对apt-get、yum或任何适合您环境的东西执行相同的操作。与此同时,我将更新注册表中的myserver:最新映像,以便任何新的容器都将基于最新映像。

我很想知道是否有任何现有技术可以解决这个问题。

更新

这主要是查询容器不更新作为构建图像是要做的方法

我也有同样的问题,所以我创建了< >强docker-run < / >强,这是一个非常简单的命令行工具,运行在集装箱码头工人中,以更新其他运行容器中的包。

它使用docker-py与正在运行的docker容器通信,更新包或运行任意单个命令

例子:

# EYZ0

默认情况下,它将在所有正在运行的容器中运行date命令并返回结果,但你可以发出任何命令,例如docker-run exec "uname -a"

更新包(目前只使用apt-get):

# EYZ0

您可以创建和别名,并将其用作常规命令行 例如< / p >

# EYZ0

在评估答案和研究主题之后,我想总结一下。

Docker升级容器的方式如下:

# EYZ0。通过这种方式,你可以在任何时候通过执行如下命令将应用程序容器替换为更新的版本:

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

您可以将数据存储在主机上(在作为卷挂载的目录中)或特殊的纯数据容器(年代)中。阅读更多相关信息

# EYZ0。应用程序容器应该是不可变的,它应该保证可复制的行为。一些官方的应用程序映像(特别是mysql:5.6)甚至没有被设计为自我更新(apt-get升级不起作用)。

我要感谢每个给出答案的人,这样我们才能看到不同的方法。

http://blog.stefanxo.com/2014/08/update-all-docker-images-at-once/

您可以使用以下命令管道更新所有现有的映像:

docker images | awk '/^REPOSITORY|\<none\>/ {next} {print $1}' | xargs -n 1 docker pull

我不喜欢挂载卷作为到主机目录的链接,所以我提出了一个模式,用完全由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容器的位置;因此,如果升级失败,您可以通过再次旋转原来的docker容器轻松恢复到以前的工作方式。

我想补充的是,如果你想自动完成这个过程(下载、停止和重新启动一个新容器,设置与@Yaroslav所描述的相同),你可以使用WatchTower。当容器被更改https://github.com/v2tec/watchtower时自动更新的程序

确保您将所有持久数据(配置、日志或应用程序数据)都用于卷,这些数据存储在与容器内进程状态相关的容器上。更新Dockerfile并使用您想要的更改重新构建映像,并重新启动容器,将卷挂载到相应的位置。

考虑以下答案:

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

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

这被认为是一种不好的做法,因为如果你丢失了容器,你就会丢失数据。虽然这是一个不好的做法,但这里有一个可行的方法:

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容器

使用外部卷是一种更好的管理数据的方法,它使更新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 images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull

只是为了提供一个更一般的(不是mysql特定的)答案…

  1. 简而言之

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

docker-compose pull

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

docker-compose up -d
  1. 背景
容器映像管理是使用docker-compose的原因之一 (见# EYZ0) < / p >

如果某个服务存在现有的容器,并且该服务的配置或映像在容器创建之后发生了更改,那么docker-compose up将通过停止并重新创建容器(保留已挂载的卷)来获取更改。为了防止Compose拾取更改,请使用——no- rebuild标志。

数据管理方面也由docker-compose通过挂载外部“卷”(参见https://docs.docker.com/compose/compose-file/#volumes)或数据容器来覆盖。

这就留下了潜在的向后兼容性和数据迁移问题,但这些都是“应用程序”问题,而不是Docker特有的问题,必须根据发布说明和测试进行检查……

下面是在构建自定义的Dockerfile时使用docker-compose的样子。

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

编辑- - - - - -

我上面的步骤比实际需要的更冗长。通过在docker-compose文件中包含build: .参数,我优化了我的工作流程。现在的步骤是这样的:

  1. 验证我的Dockerfile是我想要的样子。
  2. 在docker-compose文件中设置映像名称的版本号。
  3. 如果我的映像还没有构建:运行docker-compose build
  4. 运行# EYZ0

我当时没有意识到,但是docker-compose足够智能,只需用一个命令就可以将我的容器更新为新的映像,而不必先将其关闭。

如果你不想使用Docker Compose,我可以推荐集装箱岸吊。它有一个重建函数,可以让您在提取最新图像的同时重新创建容器。

从这里开始我尝试了很多东西,但最终还是成功了。 如果你在容器上有AutoRemove: On,你不能停止和编辑容器,或者一个服务正在运行,即使是暂时不能停止, 你必须:< / p >

PULL最新图片——># EYZ0 验证是否提取了正确的图像,您可以在Portainer Images部分

中看到UNUSED标记

使用Portainer或CLI更新服务,并确保您使用的是映像的最新版本,Portainer将为您提供相同的选项。

这不仅会更新容器的最新映像,而且还会保持服务运行。