缘起
这是介绍docker容器的第四篇文章。本系列其他文章链接如下:
- 容器(1):容器相关知识简介——容器化、docker、docker-compose、Kubernetes / K8s等
- 容器(2):docker最佳实践指南——docker-compose和Portainer
- 容器(3):docker最佳实践指南——数据卷volume的管理
在创建了容器之后,我们可能需要对容器进行更新或者升级,以便使用新的功能或者修复bug。如果我们更换了服务器,或者升级了电脑的硬件,则可能需要将容器迁移到新服务器上,或者迁移到新硬盘上。
事先声明:如果容器的官方文档中有关于更新、升级或者迁移的说明,请优先参考官方文档。本文仅针对一般性的容器更新、升级和迁移进行介绍。
前提
- 已安装Docker和docker-compose
- 了解Docker的基本概念和基本用法
- 使用docker-compose管理容器(如果你没有使用docker-compose管理容器,也不想使用docker-compose管理容器,那么本篇文章仅供参考)
更改容器
无论是更新、升级还是迁移容器,其本质都是要对原容器做一些改动,这里我们需要明确是对容器的哪一部分做了改动。一般来讲,对容器的改动涉及到以下几个部分:
- 镜像:容器是由镜像创建的,如果要用到容器的新功能、修复bug,或者想要还原回容器的旧功能,都需要对镜像进行更新或者替换。这个通常是最常见,也是最方便的改动。因为普通用户通常都是镜像的使用者,而不是镜像的创建者。我们只需要从仓库拉取新的镜像,或者删除旧的镜像,不需要关心太多其他的。
- 容器配置:容器的配置是指容器的运行参数,例如环境变量、端口映射、数据卷挂载等。一般来讲:
- 在更新或升级容器时,我们需要查阅官方文档或者更新说明,看是否新增了新的配置项,或者修改了旧的配置项。我们需要根据官方文档或者更新说明来修改容器的配置。否则,更新或升级容器时不需要修改容器的配置。
- 在迁移容器时,我们需要根据新的服务器的环境来修改容器的配置,例如修改数据卷的挂载路径、端口映射等。
- 数据:这里的数据分为两类
- 软件配置数据:这里的软件配置是指容器中运行的软件的配置,例如数据库的配置、web服务的配置等。一般来讲,软件的配置是存放在容器专门创建的数据卷中的,
- 在更新或升级容器时,我们往往不需要做什么操作,升级后的容器回继承之前的软件配置。
- 在迁移容器时,我们需要将储存软件配置的数据卷迁移到新的服务器上,或者新的硬盘上。
- 用户数据:用户的数据是指用户上传到容器中的数据,例如用户上传的图片、视频等。以及软件用户本身的帐户、密码之类的数据。一般来讲,用户的数据是以数据库或者以文件夹的形式存放在数据卷中的,我们在更新或者迁移容器时,最关注的就是这些数据。
更新、升级容器的基本流程
更新、升级容器的基本流程如下:
确定版本
在更新或者升级容器之前,我们需要确定要更新或者升级到哪个版本。一般来讲,容器的版本号是由镜像的标签(tag)来决定的。我们可以通过以下命令来查看当前容器的版本号:
|
|
或者
|
|
或者在Portainer中查看容器的详细信息,找到镜像的标签(tag)信息。
需要注意的是,很多容器在创建时往往会使用latest
标签,这个标签是指最新的版本,而且网上很多教程中也会给镜像加上latest
标签。我之前创建容器时也一直这样用,但后来发现这其实并不是一个好习惯,因为如果长时间没有更新容器,那么我们的容器和实际上仓库里的最新版本可能会有很大的差距。我们在更新或者升级容器时,就可能会遇到一些问题。而且我们也不能直观地看到我们的容器和最新的版本之间的差距。在备份和迁移容器时也不好标记。
因此,我建议在创建容器时,尽量使用具体的版本号,而不是latest
标签。这样我们想更新容器时,去官方仓库查一下最新的版本号是多少,如果跟旧容器的版本号差距不大,就可以直接更新了。如果差距很大,我们可能需要一个版本一个版本地更新。
更新升级容器
在使用docker-compose管理容器时,更新或者升级容器一般分3步:
- 停止容器
|
|
或者
|
|
- 修改docker-compose.yml文件
- 修改镜像的标签(tag),将版本号更改为新的版本号
- 修改其他配置项(如果需要)
- 重新创建容器
|
|
这个命令在检测到我们更新了镜像版本号时,会自动拉取新的镜像,并重新创建容器。
如果当前容器的版本号和最新的版本号差距很大,我们可能需要一个版本一个版本地更新。例如我之前在创建了GitLab的容器后,将近两年都没更新过,结果和最新版差了2个大版本,十几个小版本。这时如果直接更新到最新版本,就会因为兼容性等问题导致容器无法启动。GitLab在这方面其实做得还不错,如果你查看log,会发现它会提示你:
|
|
这说明我们不能直接从16.0.4
升级到16.7.0
,而是需要先升级到16.3.x
版本。但我在实际测试中发现,从16.0.4
似乎也不能直接升级到16.3.0
,只能先升级到16.1.0
。总之,最后花了我近两个小时到时间,逐步更新了十几个版本,才将GitLab更新到最新版本。
迁移容器
迁移容器更复杂一些,主要是因为我们需要把数据卷迁移到新电脑或新硬盘上,还要保证容器能正确地读取数据卷中的数据。
确定容器镜像版本、数据卷位置
在迁移容器前,我们需要确定容器的镜像版本,以免出现不兼容的问题。镜像版本号的问题在上文已经说过了,我们在创建容器时尽量使用具体的版本号,而不是latest
标签,以便在迁移时能清楚地知道容器的版本号。如果不知道,可以用上面提到的命令查看。
数据卷的位置可以在docker-compose.yml
文件中查看,有以下几种情况:
-
命名卷:命名卷的名称是唯一的,可以通过名称来访问数据卷。命名卷的数据存储在宿主机上的
/var/lib/docker/volumes
目录下。 -
绑定挂载:绑定挂载的数据卷,其位置就是定义中冒号前的那个路径。如果是只读的绑定挂载,我们在迁移时一般不需要管它。
-
临时卷:临时卷的数据存储在宿主机上的
/var/lib/docker/containers
目录下。临时卷的数据在容器停止或删除时会被删除,因此我们在迁移时一般不需要管它。 -
匿名卷:我们应该避免使用匿名卷。如果非要使用,其数据在容器停止或删除时会被删除,一般也不需要管它。
迁移数据卷
迁移数据卷和普通的迁移文件有所不同,主要是需要注意数据卷的权限问题。如果迁移后某些文件的权限变了,可能会导致容器无法访问数据卷中的文件。我们可以使用rsync
命令来迁移数据卷,具体命令如下:
|
|
rsync
命令是一个用于文件同步和备份的工具,可以在本地或远程计算机之间高效地复制和同步文件。它支持增量备份、压缩传输、保留文件权限等功能,非常适合用于迁移数据卷。
其中,-a
表示以归档模式复制文件,保留文件的权限、时间戳等信息;-H
表示保留硬链接;-A
表示保留ACL权限;-X
表示保留扩展属性;--progress
表示显示复制进度。
另外:
-
如果使用上述命令时遇到某些文件无法复制的问题,可以
sudo
来提升权限,例如:1
sudo rsync -aHAX --progress /path/to/source/ /path/to/destination/
-
如果目的地是本地的另一个目录,其中已经有一些文件了,
rsync
会自动跳过这些文件,只复制源目录中不存在的文件。如果目标目录中存在一些源目录中不存在的文件,你想把它们删除,可以加上--delete
选项。1
rsync -aHAX --progress --delete /path/to/source/ /path/to/destination/
-
如果源文件和目标文件不在同一台机器上,可以使用远程电脑的地址来复制,例如:
1
rsync -aHAX --progress /path/to/source/ user@remote:/path/to/destination/
-
如果远程电脑使用的不是22端口,可以使用
-e
选项指定ssh的端口,例如:1
rsync -aHAX --progress -e "ssh -p 2222" /path/to/source/ user@remote:/path/to/destination/
-
如果远程电脑使用的是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
文件之后,我们可以使用以下命令重新创建容器了:
|
|
如果是第一次启动容器,或者需要重新构建容器,可以使用:
|
|
如果一切顺利,容器就迁移成功了!