- 发布于
Docker volume 跨服务器迁移
- 作者
- 姓名
前言
本文是 Docker 系列文章的第四篇,Docker volume 的跨服务器迁移。本文暂不讨论 Docker 容器的迁移,只讨论数据的迁移,要解决的问题很明确,就是使用 Docker 搭建了各种服务后,万一需要更换服务器,数据如何无损的由一台服务器迁移到另一台服务器。
这个问题比我想象的要复杂,在官方推荐我们使用卷(volume)进行数据存储时,曾提到过这将方便迁移,但实际上,当面临迁移服务器这一问题时,直接使用文件夹绑定的方式更为方便,只需要将文件夹复制到新服务器即可,若使用了 volume,直接复制到新的服务器中的/var/lib/docker/volumes
文件夹下并不会生效,需要修改对应的配置文件,既不方便也不优雅。
本文参考了官方指南以及 stackoverflow
上的多个回答,将不省略任何细节,用最清晰的方式讲清楚这一问题。
实现流程
要对容器 volume 进行迁移,主要流程如下:
- 打包现有 volume 内容为 tar 文件
- 将 tar 文件传输至新服务器
- 在新服务器中创建中间容器
- 解压 tar 文件至 volume 对应目录
- 清理中间容器等
打包现有 volume 内容为 tar 文件
实现这一步操作的方式主要使用了 --volumes-from CONTAINER
这一命令,这一命令的功能是挂载其他容器的 volume。
为了实现打包现有 volume 内容,我们需要创建一个中间容器,这个容器的作用就是在挂载了需要备份的 volume 之后,在该容器中使用 tar 命令将其对应的文件夹打包,并通过文件夹映射的方式,将打包的文件共享至宿主机中。
作为中间容器的镜像可以自由选择, stackoverflow 回答中使用了 busybox,这里就以 busybox 为例:
docker run --rm --volumes-from CONTAINER -v $(pwd):/backup busybox tar cvf /backup/backup.tar /DIR_TO_BAKUP
为了更加清晰,将上面的命令进行分行如下:
docker run --rm --volumes-from CONTAINER \
-v $(pwd):/backup \
busybox \
tar cvf /backup/backup.tar -C /DIR_TO_BAKUP ./
命令中大写字母内容就是我们需要修改的,CONTAINER 需要修改为需要备份 volume 的容器名,/DIR_TO_BAKUP 需要修改为 volume 在容器中的路径,对命令的各行进行解释如下:
--rm
表示该容器是一次性环境,生成后就自动删除,我们只需要运行一次备份文件而已-v $(pwd):/backup
表示我们将容器的/backup
目录映射到主机当前目录- busybox 镜像名,这里也可以替换为其他镜像
tar cvf /backup/backup.tar -C /DIR_TO_BAKUP ./
表示将容器中/DIR_TO_BAKUP
文件夹的内容打包,并存储在/backup
文件夹下,文件名为backup.tar
,结合前面那行-v $(pwd):/backup
就可以实现将 volume 内容打包为宿主机当前目录下的backup.tar
文件
请注意,在测试后对这里进行了修改,增加了 -C 参数,增加 -C 参数可以避免出现打包的文件包括了我们不需要的目录,比如我们想要打包的是
/var/lib/mysql
目录下的全部文件,使用了 -C 参数并结合最后的 ./ 可以避免最终生成的 tar 文件解压后包括/var/lib/mysql
将 tar 文件传输至新服务器
这一步可以各显神通,既可以通过 FTP 下载上传,也可以使用 rsync 工具进行传输,我们采用 rsync 进行传输,这需要你拥有原服务器的 SSH 权限。
具体流程如下:
- SSH连接新服务器,并在新服务器中安装 rsync
sudo apt-get update
sudo apt-get install rsync
- 使用 rsync 将备份文件复制至新服务器
rsync 的更多使用方式请自行搜索,这里我们通过 SSH 方式进行传输,命令形式为 rsync -av 原服务器IP:原服务器中文件 目标文件夹
我们将前文备份的 backup.tar 文件复制至新服务器的当前目录为例:
rsync -av --progress root@原服务器IP:/root/backup.tar .
可以在本地安装 rsync 作为中转,下载完备份文件后再上传到新服务器:
rsync -av --progress backup.tar root@新服务器IP:/root/
在新服务器创建中间容器
通过前面的操作,我们已经成功的将原服务器中的 volume 以 tar 文件形式传输到了新服务器,下面的工作就是如何将该 tar 文件转换为 volume。
首先我们需要使用 docker create
命令创造一个仅用于迁移的容器:
docker create -v TARGET_VOLUME_NAME:/data --name for_migrate busybox true
其中
TARGET_VOLUME_NAME
请修改为你的目标 volume 名,/data
是 volume 在容器内对应的文件夹,既然只是中间容器无须修改,for_migrate
名字随你心情
解压 tar 文件至 volume 对应目录
我们通过一次性容器将备份的 tar 文件内容解压缩至 volume 中:
docker run --rm --volumes-from for_migrate -v $(pwd):/backup busybox tar xvf /backup/backup.tar -C data/
更清晰的分行形式:
docker run --rm --volumes-from for_migrate \
-v $(pwd):/backup \
busybox \
tar xvf /backup/backup.tar -C data/
如果你按照前文的操作,在新服务器当前文件夹下有一个
backup.tar
文件,就可以直接使用上面的命令,如果你的操作与前文有差异,请自行修改对应的文件夹 解压时同样使用了 -C 参数,读者可自行了解 tar 命令说明
其他工作
通过上面的操作,你已经成功的将旧服务器中的 volume 迁移到了新服务器。这时我们将中间容器 for_migrate 删除即可,全部工作到此就算基本完成了。
现在你可以将生成的 volume 应用到其他容器了,通过 docker export
从旧服务器恢复容器或者直接创建新容器都可以。
实例操作
本文已经通过本人 Nextcloud 服务器迁移测试成功,所有文件和配置全部成功迁移,之前生成的共享链接也没有发生变化,为了本文读者能更清晰的了解这一过程,下面将增加 Ghost 博客的迁移示例。
本次示例将直接以本站进行示范,本站使用了反向代理隐藏了服务器真实IP,为避免服务器IP泄漏,下文中出现的原服务器IP均已经过处理,新服务器是一台 DigitalOcean 的服务器,本文完成后即销毁
本次迁移的新服务器IP地址为 209.97.168.182
,两台服务器均使用 Ubuntu 18.04 系统,本次迁移的 Ghost 数据库使用 sqlite 不使用 mysql,因此也不使用 docker-compose 搭建,仅包括一个 volume。
原服务器打包
原服务器 Ghost 容器名为 ghost
,volume 名为ghost_content
,对应的容器内目录为/var/lib/ghost/content
,这些信息可以通过docker inspect CONTAINER
获得。
打包的命令如下:
docker run --rm --volumes-from ghost -v $(pwd):/backup busybox tar cvf /backup/backup.tar -C /var/lib/ghost/content ./
运行之后等待 tar 完成打包即可,当前目录下将出现 backup.tar 文件。
传输数据至新服务器
可参考上文使用 rsync 传输,也可以使用 sftp 传输,由于服务器仅开放了密钥登录,又不想绑定新服务器密钥(需要重启太麻烦),测试时使用了 sftp 传输至本地后再由本地 sftp 上传至目标服务器。
新服务器创建中间容器
我们沿用原服务器中 volume 的名称ghost_content
,当然这个不沿用也没任何问题,需要注意的是,如果这是通过 docker-compose 创建的容器,在 docker-compose.yml中的 volume 名都会被添加前缀,在命名 volume 的时候需要注意匹配。
docker create -v ghost_content:/data --name for_migrate busybox true
将数据解压至 volume
docker run --rm --volumes-from for_migrate -v $(pwd):/backup busybox tar xvf /backup/backup.tar -C data/
删除中间容器
docker rm for_migrate
使用恢复的 volume 创建新的 Ghost 容器
docker run -d --name ghost -p 2368:2368 \
-v ghost_content:/var/lib/ghost/content \
ghost
运行上面的命令后,我们就使用恢复的 volume 创建了新的 Ghost 容器,如果需要保证兼容性,可以在 ghost 后增加原服务器中所使用的版本 Tag,相应的版本 Tag 可以查看其镜像的 Docker Hub 主页。
我们访问http://209.97.168.182:2368,可以看到已经将原服务器数据完好的迁移到了新服务器:
此时到nginx反向代理服务器中再配置一下反代地址,我们就将网站完好的迁移到了新的服务器。
一点小问题
测试中发现左上角的 LOGO 会链接到http://localhost:2368,这需要我们对/var/lib/ghost
目录下的config.production.json
文件进行修改,我们需要进入容器内部,安装 vim 后对该文件进行修改。
docker exec -it ghost /bin/bash
修改上面命令后将会进入 Ghost 容器内部,我们安装 vim:
apt-get update
apt-get install vim
之后继续在容器内部修改config.production.json
:
vim config.production.json
将第一行的内容改成你的网站网址即可:
为了方便修改配置,也可以选择将
/var/lib/ghost
文件夹映射到宿主机中。
参考内容
本文撰写参考了以下内容,向作者表示感谢: