Featured image of post 容器(4):docker最佳实践指南——容器更新、升级和迁移

容器(4):docker最佳实践指南——容器更新、升级和迁移

使用docker的最佳方法——如何更新、升级或者迁移容器

缘起

这是介绍docker容器的第四篇文章。本系列其他文章链接如下:

在创建了容器之后,我们可能需要对容器进行更新或者升级,以便使用新的功能或者修复bug。如果我们更换了服务器,或者升级了电脑的硬件,则可能需要将容器迁移到新服务器上,或者迁移到新硬盘上。

事先声明:如果容器的官方文档中有关于更新、升级或者迁移的说明,请优先参考官方文档。本文仅针对一般性的容器更新、升级和迁移进行介绍。

前提

  • 已安装Docker和docker-compose
  • 了解Docker的基本概念和基本用法
  • 使用docker-compose管理容器(如果你没有使用docker-compose管理容器,也不想使用docker-compose管理容器,那么本篇文章仅供参考)

更改容器

无论是更新、升级还是迁移容器,其本质都是要对原容器做一些改动,这里我们需要明确是对容器的哪一部分做了改动。一般来讲,对容器的改动涉及到以下几个部分:

  1. 镜像:容器是由镜像创建的,如果要用到容器的新功能、修复bug,或者想要还原回容器的旧功能,都需要对镜像进行更新或者替换。这个通常是最常见,也是最方便的改动。因为普通用户通常都是镜像的使用者,而不是镜像的创建者。我们只需要从仓库拉取新的镜像,或者删除旧的镜像,不需要关心太多其他的。
  2. 容器配置:容器的配置是指容器的运行参数,例如环境变量、端口映射、数据卷挂载等。一般来讲:
  • 在更新或升级容器时,我们需要查阅官方文档或者更新说明,看是否新增了新的配置项,或者修改了旧的配置项。我们需要根据官方文档或者更新说明来修改容器的配置。否则,更新或升级容器时不需要修改容器的配置。
  • 在迁移容器时,我们需要根据新的服务器的环境来修改容器的配置,例如修改数据卷的挂载路径、端口映射等。
  1. 数据:这里的数据分为两类
  • 软件配置数据:这里的软件配置是指容器中运行的软件的配置,例如数据库的配置、web服务的配置等。一般来讲,软件的配置是存放在容器专门创建的数据卷中的,
    • 在更新或升级容器时,我们往往不需要做什么操作,升级后的容器回继承之前的软件配置。
    • 在迁移容器时,我们需要将储存软件配置的数据卷迁移到新的服务器上,或者新的硬盘上。
  • 用户数据:用户的数据是指用户上传到容器中的数据,例如用户上传的图片、视频等。以及软件用户本身的帐户、密码之类的数据。一般来讲,用户的数据是以数据库或者以文件夹的形式存放在数据卷中的,我们在更新或者迁移容器时,最关注的就是这些数据。

更新、升级容器的基本流程

更新、升级容器的基本流程如下:

确定版本

在更新或者升级容器之前,我们需要确定要更新或者升级到哪个版本。一般来讲,容器的版本号是由镜像的标签(tag)来决定的。我们可以通过以下命令来查看当前容器的版本号:

1
docker inspect <container_name> | grep Image

或者

1
docker inspect <container_name> | grep RepoTags

或者在Portainer中查看容器的详细信息,找到镜像的标签(tag)信息。

需要注意的是,很多容器在创建时往往会使用latest标签,这个标签是指最新的版本,而且网上很多教程中也会给镜像加上latest标签。我之前创建容器时也一直这样用,但后来发现这其实并不是一个好习惯,因为如果长时间没有更新容器,那么我们的容器和实际上仓库里的最新版本可能会有很大的差距。我们在更新或者升级容器时,就可能会遇到一些问题。而且我们也不能直观地看到我们的容器和最新的版本之间的差距。在备份和迁移容器时也不好标记。

因此,我建议在创建容器时,尽量使用具体的版本号,而不是latest标签。这样我们想更新容器时,去官方仓库查一下最新的版本号是多少,如果跟旧容器的版本号差距不大,就可以直接更新了。如果差距很大,我们可能需要一个版本一个版本地更新。

更新升级容器

在使用docker-compose管理容器时,更新或者升级容器一般分3步:

  1. 停止容器
1
sudo docker-compose stop

或者

1
sudo docker-compose down
  1. 修改docker-compose.yml文件
  • 修改镜像的标签(tag),将版本号更改为新的版本号
  • 修改其他配置项(如果需要)
  1. 重新创建容器
1
sudo docker-compose up -d

这个命令在检测到我们更新了镜像版本号时,会自动拉取新的镜像,并重新创建容器。

如果当前容器的版本号和最新的版本号差距很大,我们可能需要一个版本一个版本地更新。例如我之前在创建了GitLab的容器后,将近两年都没更新过,结果和最新版差了2个大版本,十几个小版本。这时如果直接更新到最新版本,就会因为兼容性等问题导致容器无法启动。GitLab在这方面其实做得还不错,如果你查看log,会发现它会提示你:

1
2
3
4
5
It seems you are upgrading from 16.0.4-ee to 16.7.0.
It is required to upgrade to the latest 16.3.x version first before proceeding.
Please follow the upgrade documentation at https://docs.gitlab.com/ee/update/#upgrade-paths
Thank you for using GitLab Docker Image!
Current version: gitlab-ee=16.7.0-ee.0

这说明我们不能直接从16.0.4升级到16.7.0,而是需要先升级到16.3.x版本。但我在实际测试中发现,从16.0.4似乎也不能直接升级到16.3.0,只能先升级到16.1.0。总之,最后花了我近两个小时到时间,逐步更新了十几个版本,才将GitLab更新到最新版本。

GitLab更新

迁移容器

迁移容器更复杂一些,主要是因为我们需要把数据卷迁移到新电脑或新硬盘上,还要保证容器能正确地读取数据卷中的数据。

确定容器镜像版本、数据卷位置

在迁移容器前,我们需要确定容器的镜像版本,以免出现不兼容的问题。镜像版本号的问题在上文已经说过了,我们在创建容器时尽量使用具体的版本号,而不是latest标签,以便在迁移时能清楚地知道容器的版本号。如果不知道,可以用上面提到的命令查看。

数据卷的位置可以在docker-compose.yml文件中查看,有以下几种情况:

  1. 命名卷:命名卷的名称是唯一的,可以通过名称来访问数据卷。命名卷的数据存储在宿主机上的/var/lib/docker/volumes目录下。

  2. 绑定挂载:绑定挂载的数据卷,其位置就是定义中冒号前的那个路径。如果是只读的绑定挂载,我们在迁移时一般不需要管它。

  3. 临时卷:临时卷的数据存储在宿主机上的/var/lib/docker/containers目录下。临时卷的数据在容器停止或删除时会被删除,因此我们在迁移时一般不需要管它。

  4. 匿名卷:我们应该避免使用匿名卷。如果非要使用,其数据在容器停止或删除时会被删除,一般也不需要管它。

迁移数据卷

迁移数据卷和普通的迁移文件有所不同,主要是需要注意数据卷的权限问题。如果迁移后某些文件的权限变了,可能会导致容器无法访问数据卷中的文件。我们可以使用rsync命令来迁移数据卷,具体命令如下:

1
rsync -aHAX --progress /path/to/source/ /path/to/destination/

rsync命令是一个用于文件同步和备份的工具,可以在本地或远程计算机之间高效地复制和同步文件。它支持增量备份、压缩传输、保留文件权限等功能,非常适合用于迁移数据卷。 其中,-a表示以归档模式复制文件,保留文件的权限、时间戳等信息;-H表示保留硬链接;-A表示保留ACL权限;-X表示保留扩展属性;--progress表示显示复制进度。

另外:

  1. 如果使用上述命令时遇到某些文件无法复制的问题,可以sudo来提升权限,例如:

    1
    
    sudo rsync -aHAX --progress /path/to/source/ /path/to/destination/
    
  2. 如果目的地是本地的另一个目录,其中已经有一些文件了,rsync会自动跳过这些文件,只复制源目录中不存在的文件。如果目标目录中存在一些源目录中不存在的文件,你想把它们删除,可以加上--delete选项。

    1
    
    rsync -aHAX --progress --delete /path/to/source/ /path/to/destination/
    
  3. 如果源文件和目标文件不在同一台机器上,可以使用远程电脑的地址来复制,例如:

    1
    
    rsync -aHAX --progress /path/to/source/ user@remote:/path/to/destination/
    
  4. 如果远程电脑使用的不是22端口,可以使用-e选项指定ssh的端口,例如:

    1
    
    rsync -aHAX --progress -e "ssh -p 2222" /path/to/source/ user@remote:/path/to/destination/
    
  5. 如果远程电脑使用的是ssh密钥登录,可以使用-e选项指定ssh的密钥,例如:

    1
    
    rsync -aHAX --progress -e "ssh -i /path/to/key" /path/to/source/ user@remote:/path/to/destination/
    

迁移docker-compose.yml文件

之所以在迁移完数据之后再迁移docker-compose.yml文件,是因为在新电脑或新硬盘上的数据卷路径可能会发生变化。我们需要在迁移完数据之后,再修改docker-compose.yml文件中的数据卷路径。

这一步其实很简单,主要是别忘了修改数据卷的路径。

重新创建容器

在迁移完数据和docker-compose.yml文件之后,我们可以使用以下命令重新创建容器了:

1
sudo docker-compose up -d

如果是第一次启动容器,或者需要重新构建容器,可以使用:

1
sudo docker-compose up -d --build

如果一切顺利,容器就迁移成功了!

comments powered by Disqus