假设我已经取出了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的正确方式是什么?
当前回答
下面是在构建自定义Dockerfile时使用docker-compose的样子。
首先构建自定义Dockerfile,然后附加下一个版本号以进行区分。示例:docker build -t imagename:版本。这将在本地存储您的新版本。 运行docker-compose down 编辑docker-compose。Yml文件以反映在步骤1中设置的新映像名称。 运行docker-compose up -d。它将在本地查找图像并使用升级后的图像。
编辑- - - - - -
我上面的步骤比实际需要的更冗长。我已经通过包含构建优化了我的工作流程:。参数到我的docker-compose文件。现在的步骤是这样的:
验证我的Dockerfile是我想要的样子。 在docker-compose文件中设置映像名称的版本号。 如果我的映像还没有构建:运行docker-compose build 运行docker-compose up -d
我当时没有意识到,但是docker-compose足够智能,只需用一个命令就可以将我的容器更新为新的映像,而不必先将其关闭。
其他回答
与上述答案相似
docker images | awk '{print $1}' | grep -v 'none' | grep -iv 'repo' | xargs -n1 docker pull
如果你不想使用Docker Compose,我可以推荐portainer。它有一个重建函数,可以让您在提取最新图像的同时重新创建容器。
我不喜欢挂载卷作为到主机目录的链接,所以我提出了一个模式,用完全由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容器轻松恢复到以前的工作方式。
更新
这主要是查询容器不更新作为构建图像是要做的方法
我也遇到了同样的问题,所以我创建了docker-run,这是一个非常简单的命令行工具,在docker容器中运行,以更新其他运行容器中的包。
它使用docker-py与正在运行的docker容器通信,更新包或运行任意单个命令
例子:
Docker run——rm -v /var/run/ Docker .sock:/tmp/ Docker .sockSock itech/docker-run exec
默认情况下,这将在所有正在运行的容器中运行date命令并返回结果,但您可以发出任何命令,例如docker-run exec "uname -a"
更新包(目前只使用apt-get):
Docker run——rm -v /var/run/ Docker .sock:/tmp/ Docker .sockSock itech/docker-run更新
您可以创建和别名,并将其作为常规命令行使用 如。
别名docker-run='docker run——rm -v /var/run/docker.sock:/tmp/docker. sock:/tmp/docker. sock袜子itech / docker-run '
在评估答案和研究主题之后,我想总结一下。
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
您可以将数据存储在主机上(在作为卷挂载的目录中),也可以存储在特殊的仅数据容器中。阅读更多相关信息
关于卷(Docker docs) 小Docker碎片,松散连接(汤姆·奥弗曼) 如何处理Docker中的持久存储(例如数据库)(堆栈溢出问题)
升级应用程序(例如;容器中的yum/apt-get upgrade)被认为是反模式。应用程序容器被认为是不可变的,这将保证可再现的行为。一些官方的应用程序映像(特别是mysql:5.6)甚至没有被设计为自我更新(apt-get升级不起作用)。
我要感谢每个给出答案的人,这样我们才能看到不同的方法。