基于 Docker 的云服务迁移

自从上次不小心误操作丢失数据之后,我的云服务就重构过一次,现在全部采用数据卷来保存,这样当我有迁移云服务的需求的时候,就可以直接将数据卷下载好,然后迁移到其他的服务器中运行,甚至如果有一天我不在云上了,也可以在本地的 docker 上访问。那么这次就来尝试迁移,并总结经验!

基于 Docker 的云服务迁移
Photo by Ian Taylor / Unsplash

原理

我采用的方案是使用 docker compose 来配置需要的云服务,将云服务所需的数据通过 volume 数据卷来保存,并交给 docker 统一管理,而不是使用文件映射自己管理。当需要更换服务器迁移数据的时候,可以通过分别迁移数据卷和配置文件来实现云服务的无痛迁移。同时后期可以根据需求编写简单的批处理脚本实现更新云服务镜像版本、数据卷打包备份、云服务迁移等功能。

配置新的服务器

由于之前的服务器是2核1G,资源非常吃紧,我不得不动用了 Linux 的祖传技能,扩充 Swap 交换分区!在 1G 物理内存 + 3G 的交换分区的操作下,我的云服务器成功运行了各种 Docker 容器,包括一个 MySQL 8.0,据说 5 的版本比较节省内存,但我直接上了 8,卡死了。所以第一件事:

配置 Swap 交换分区

使用 free 命令查看当前的内存分区情况

free -m

接下来我们将操作 swap 分区,我们需要暂时关闭 swap 的使用。

swapoff -a

分配 2G 的交换分区,默认从 zero 的主分区中划一块出来。

dd if=/dev/zero of=/var/swapfile bs=1M count=2048

秉承一切都是文件,我们需要创建一个交换分区的文件来挂载 2G 的空间。

mkswap /var/swapfile

记得重新开启 swap 分区

swapon /var/swapfile

并将以下内容写入 /etc/fstab 文件末尾,顺便给实例改了名,重启查看是否生效。

/var/swapfile swap swap defaults 0 0

当重启后运行命令结果如下,证明配置完成,此时你已经拥有了伪2核4G的云服务器了:

root@robot:~# free -m
               total        used        free      shared  buff/cache   available
Mem:            1690         205        1152           2         332        1329
Swap:           2047           0        2047
root@robot:~#

安装 docker

这里使用官网的教程,只需要两行命令:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

配置一个普通用户

很多时候我们要避免直接在 root 用户下操作,这是非法且危险的,特别是在 docker 容器中使用带有 root 权限的一些误操作可能会导致被攻击提权,进而从容器入侵到服务器。

配置一个普通用户的最佳实践,注意将 username 替换为你需要的用户名:

useradd -d /home/<username> -m -s /bin/bash <username>

然后记得纳入编制(赋予 root 权限),首先使用 visudo 命令打开 sudoers 编辑,在 root 用户下面照搬编写一行 <username>       ALL=(ALL:ALL) ALL 记得用户名和后面使用 tab 隔开。

ok,我想我现在需要保存一下数据,并离开这里。

🤔
注意,数据迁移的时候,不要去产生任何新的数据。
😴
没想到回来已经折腾了一个多小时了,好累。

导出数据

打包数据卷的工具

我们使用了官方给到的一个小工具 docker-vackup,它可以帮助我们导出数据卷的数据,并打包到 gzip 文件中,使用下来简直没话说,比在百度上扣一坨 CSDN 的野鸡教程都来的,算了,没有可比性,这是最佳实践!

但是使用这个脚本可能会遇到没有翻墙拉不了代码的问题,不过还好这只是一个单文件的脚本,这里叫做 vackup.sh,自己复制内容,新建一个文件粘进去就可以用,这里不赘述。

打包数据卷

进入需要备份的旧服务器中,运行 docker volume ls 列出所有需要备份的数据卷,这时你有两种选择,写脚本,或者一条一条的复制,脚本的话后面再补充吧,我这里暂时是直接敲的命令。使用 ./vackup.sh import ghost_data.gz ghost_data 导出数据卷名为 ghost_data 的数据到 ghost_data.gz 中,批量操作之后可以得到一系列的 gz 文件,用你熟悉的手段传输到另一个服务器中,这里我用的土办法:

scp *.gz name@ip:/home/username

在新服务器上部署

导入数据卷

对应的使用 export 就可以了,这里不赘述,只要是没有任何改动的容器和数据卷,在打包后再重新建立起来都是完美运行的,哪怕你是存在 mysql 里的数据也可以打包!

导入 docker compose 配置文件

这里我出于良好的习惯,使用 compose 文件来保存所有的容器,所以并不存在需要导出容器的情况,容器不重要,重要的是数据,只要把关键数据通过数据卷打包过来,剩下的都可以直接通过配置来恢复。

最后启动服务,检查是否存在无法运作的容器。这里本来没有的,硬是因为误操作没有提交新版本的配置文件代码,使用 mysql 5 的配置和 mysql 8 的数据卷出现了冲突,最后反映过来就及时解决了。

最后

docker compose 来管理个人的云服务确实做到了容器化的便利,且易于管理,在小内存的机器和多种服务需求的容器管理中找到了一个折中的解决方案,此致为后人留下参考方案。