Docker备份和迁移数据

迁移方式介绍

容器中的数据,如果没有用挂载目录,删除容器后就会丢失数据。

前面我们已经讲解了如何 挂载目录

如果你是用bind mount直接把宿主机的目录挂进去容器,那迁移数据很方便,直接复制目录就好了

如果你是用volume方式挂载的,由于数据是由容器创建和管理的,需要用特殊的方式把数据弄出来。

备份和导入 Volume 的流程

备份:

  • 运行一个 ubuntu 的容器,挂载需要备份的 volume 到容器,并且挂载宿主机目录到容器里的备份目录。
  • 运行 tar 命令把数据压缩为一个文件
  • 把备份文件复制到需要导入的机器

导入:

  • 运行 ubuntu 容器,挂载容器的 volume,并且挂载宿主机备份文件所在目录到容器里
  • 运行 tar 命令解压备份文件到指定目录

备份 MongoDB 数据演示

  • 运行一个 mongodb,创建一个名叫mongo-data的 volume 指向容器的 /data 目录
    docker run -p 27018:27017 --name mongo -v mongo-data:/data -d mongo:4.4
  • 运行一个 Ubuntu 的容器,挂载mongo容器的所有 volume,映射宿主机的 backup 目录到容器里面的 /backup 目录,然后运行 tar 命令把数据压缩打包
    docker run --rm --volumes-from mongo -v d:/backup:/backup ubuntu tar cvf /backup/backup.tar /data/

最后你就可以拿着这个 backup.tar 文件去其他地方导入了。

恢复 Volume 数据演示

  • 运行一个 ubuntu 容器,挂载 mongo 容器的所有 volumes,然后读取 /backup 目录中的备份文件,解压到 /data/ 目录
    docker run --rm --volumes-from mongo -v d:/backup:/backup ubuntu bash -c "cd /data/ && tar xvf /backup/backup.tar --strip 1"

注意,volumes-from 指定的是容器名字
strip 1 表示解压时去掉前面1层目录,因为压缩时包含了绝对路径

镜像备份

1
2
3
4
5
6
7
8
# 查看需要备份的镜像
docker images

# 保存镜像
docker save -o /path/to/image_save.tar <镜像ID或名称>

# 将多个镜像打包到一个tar文件中
docker save -o images.tar <镜像1>:<标签1> <镜像2>:<标签2> ...

镜像备份脚本

docker 批量全部镜像备份脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/bin/bash

# 配置
BACKUP_PATH="/data/docker_bak" # 备份存储路径
[ -d ${BACKUP_PATH} ] || mkdir -p ${BACKUP_PATH}
# 创建备份文件名
create_backup_name() {
echo "$1_$(date +%Y%m%d%H%M)"
}

# 创建备份目录
prepare_backup_dir() {
echo "准备备份目录..."
mkdir -p "${BACKUP_PATH}"
if [ $? -ne 0 ]; then
echo "创建备份目录失败!"
exit 1
fi
}

# 获取容器的镜像名和标签
get_image_name_and_tag() {
docker inspect --format '{{.Config.Image}}' "$1"
}

# 备份 Docker 容器
backup_docker_container() {
local container_id=$1
local image_name_and_tag=$(get_image_name_and_tag "${container_id}")
local backup_name=$(create_backup_name "${container_id}")
echo "开始备份 Docker 容器: ${container_id}"
docker commit "${container_id}" "${backup_name}"
docker save -o "${BACKUP_PATH}/${backup_name}.tar" "${backup_name}"
if [ $? -ne 0 ]; then
echo "备份 Docker 容器失败:${container_id}"
exit 1
fi
echo "Docker 容器备份完成:${BACKUP_PATH}/${backup_name}.tar"
}

# 主函数
main() {
prepare_backup_dir
# 获取所有运行中的容器ID
#container_ids=$(docker container ls --quiet)
container_ids=$(docker ps -a -q)
if [ -z "${container_ids}" ]; then
echo "没有找到正在运行的容器。"
exit 1
fi
# 遍历所有容器ID并备份
for container_id in $container_ids; do
backup_docker_container "${container_id}"
done
}

# 执行主函数
main

镜像导入

1
docker load -i xxx.tar

容器导出

1
docker export <容器ID或名称> > /path/to/container_export.tar

容器导入

1
cat /path/to/container_export.tar | docker import - <新镜像名称>:<标签>

注意

上述内容分为数据卷备份与导入镜像备份与导入容器备份与导入不可混为一谈,根据自己需求。

只备份容器然后导入其他Docker是否会携带镜像

当你只备份容器并尝试在另一台Docker环境中导入时,需要注意的是,导入的容器并不包含其原始镜像。容器是基于镜像创建的,但导出的容器文件(使用docker export命令)仅包含容器的文件系统快照,而不包含镜像的层次结构和元数据。因此,在导入容器时,Docker会将其视为一个新的镜像,但这个新镜像并不包含原始镜像的所有层和依赖关系。

如果你希望在另一台Docker环境中运行相同的容器,并且希望保留其原始镜像的所有层和依赖关系,那么你应该备份并迁移镜像(使用docker savedocker load命令),而不是仅备份容器。

备份容器、备份镜像与备份数据卷的区别

  1. 备份容器
    • 使用docker export命令导出容器的文件系统快照。
    • 备份的文件不包含镜像的层次结构和元数据,仅包含容器的当前状态。
    • 导入容器时,会创建一个新的镜像,但这个新镜像与原始镜像不同。
  2. 备份镜像
    • 使用docker save命令保存镜像的所有层和元数据。
    • 备份的文件包含镜像的完整结构和依赖关系。
    • 导入镜像时,会恢复原始镜像的所有层和依赖关系。
  3. 备份数据卷
    • 数据卷是Docker中用于持久化数据的特殊目录或文件。
    • 使用docker cp命令或其他文件传输工具备份数据卷的内容。
    • 备份的数据卷内容可以在新环境中重新创建数据卷并复制回去。

总结

  • 备份容器适用于需要迁移容器的当前状态但不关心其原始镜像的场景。
  • 备份镜像适用于需要迁移容器的完整环境和依赖关系的场景。
  • 备份数据卷适用于需要持久化容器产生的数据并确保数据安全的场景。

在进行Docker迁移和备份操作时,请根据实际需求选择合适的备份方式,并确保在迁移前后验证备份文件的完整性和可用性。

简单粗暴

上边讲了很多很多,太过于复杂,下面来个简单粗暴的迁移

导出

1
2
3
4
5
6
7
8
9
10
# 1. 压缩容器数据挂载目录 数据库挂载目录同样
# 比如:docker run -itd --name devops_xxx_test -v /home/data/jerry/devops/xxx_testServer:/devops/xxx_testServer -p 15000-15009:8000-8009 b5ee597f2028_202501081551
zip -r devops_xxx_test.zip /home/data/jerry/devops/xxx_testServer/*

# 2. 我一般直接用上面的批量镜像备份脚本
# 查看需要备份的镜像
docker images

# 保存镜像
docker save -o /path/to/image_save.tar <镜像ID或名称>

导入

1
2
3
4
5
6
7
8
# 1. 导入备份的镜像文件
docker load -i image_save.tar
# 2. 用rsync、scp、wget等其他方法复制你压缩的数据包 到 迁移后服务器里
unzip devops_xxx_test.zip -d <解压的目录>
# 3. 创建容器
docker run -itd --name <容器名称> -v <解压的目录>:<容器映射目录> -p <外部端口>:<映射容器端口> <镜像ID或名称>
# 4. 启动容器
docker start <容器名称>

文笔流畅美,点赞纷至来;

内容引入胜,分享乐开怀;

佳作值得赏,打赏表心怀。