如何将 Docker 卷迁移到另一台主机

DockerBeginner
立即练习

介绍

Docker 卷为容器化应用提供了持久性存储,即使容器停止或移除,数据也能保持完整。随着你的基础设施不断发展,你可能需要将这些卷迁移到不同的主机上,以支持扩展、升级或服务的重新部署。

本教程将指导你完成在主机之间迁移 Docker 卷的过程。你将学习如何创建卷、用数据填充卷、备份卷,以及在新主机上恢复卷。通过完成本实验,你将清楚地了解 Docker 卷迁移技术,以确保在你的容器化环境中数据持续可用。

理解和创建 Docker 卷

Docker 卷为你的容器提供持久性存储。在迁移卷之前,你需要了解它们是什么以及如何创建它们。

什么是 Docker 卷?

Docker 卷是持久化由 Docker 容器生成和使用的数据的首选机制。与存储在容器的可写层中的数据(在容器被移除时会丢失)不同,卷完全由 Docker 管理,并且独立于容器存在。

Docker 卷的一些主要优点包括:

  • 数据在容器生命周期中的持久性
  • 能够在容器之间共享数据
  • 比容器的文件系统更好的性能
  • 独立于容器的管理

创建你的第一个 Docker 卷

让我们从创建一个简单的 Docker 卷开始:

docker volume create my-data-volume

当你运行此命令时,Docker 将创建一个名为 my-data-volume 的新卷。你应该在终端中看到卷名称被打印出来:

my-data-volume

你可以使用以下命令列出系统上的所有 Docker 卷:

docker volume ls

这将显示一个包含所有卷的表格:

DRIVER    VOLUME NAME
local     my-data-volume

检查 Docker 卷

要获取有关你的卷的更多详细信息,请使用 inspect 命令:

docker volume inspect my-data-volume

你将以 JSON 格式看到有关卷的详细信息:

[
  {
    "CreatedAt": "2023-10-01T12:34:56Z",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/my-data-volume/_data",
    "Name": "my-data-volume",
    "Options": {},
    "Scope": "local"
  }
]

注意 Mountpoint 值——这是 Docker 在主机系统上存储卷数据的位置。

将 Docker 卷与容器一起使用

现在你已经创建了一个卷,让我们将其与容器一起使用。我们将创建一个简单的容器,该容器挂载卷并将一些数据添加到其中:

docker run --name my-container -v my-data-volume:/data ubuntu /bin/bash -c "echo 'Hello from Docker volume' > /data/test.txt"

此命令:

  • 创建一个名为 my-container 的容器
  • my-data-volume 挂载到容器内的 /data 目录
  • 运行一个简单的命令,将文本写入该目录中的文件

让我们通过创建另一个挂载相同卷的容器来验证数据是否已写入卷:

docker run --rm -v my-data-volume:/data ubuntu cat /data/test.txt

你应该看到输出:

Hello from Docker volume

这表明数据保留在卷中,并且可以被不同的容器访问。

准备卷迁移

在将 Docker 卷迁移到另一台主机之前,我们需要准备我们的源数据并了解迁移过程。在此步骤中,我们将向我们的卷添加更多数据并准备进行迁移。

向卷添加更多数据

让我们创建一个容器,该容器将向我们的卷添加更多数据。这将有助于演示所有卷数据都已正确迁移:

docker run --name data-generator -v my-data-volume:/data ubuntu /bin/bash -c "mkdir -p /data/config && echo 'database_url=postgres://user:password@db:5432/mydb' > /data/config/settings.conf && echo 'This is important data' > /data/important.txt"

此命令在我们的卷中创建具有示例内容的目录和文件。

让我们验证卷中的数据结构:

docker run --rm -v my-data-volume:/data ubuntu ls -la /data

你应该看到类似这样的输出:

total 12
drwxr-xr-x 3 root root 4096 Oct  1 12:34 .
drwxr-xr-x 1 root root 4096 Oct  1 12:34 ..
drwxr-xr-x 2 root root 4096 Oct  1 12:34 config
-rw-r--r-- 1 root root   21 Oct  1 12:34 important.txt
-rw-r--r-- 1 root root   24 Oct  1 12:34 test.txt

我们还检查一下其中一个文件的内容:

docker run --rm -v my-data-volume:/data ubuntu cat /data/important.txt

输出:

This is important data

了解卷迁移方法

有几种迁移 Docker 卷的方法:

  1. 直接主机到主机复制(Direct host-to-host copy):直接在主机之间复制卷数据
  2. 备份和恢复(Backup and restore):创建备份存档并在新主机上恢复它
  3. 使用 Docker 插件(Using Docker plugins):某些存储插件具有内置的复制功能

对于本实验,我们将使用备份和恢复方法,该方法适用于大多数环境,并且不需要特殊的插件。

创建卷的备份

要创建我们卷的备份,我们将使用 Docker 容器来存档卷内容:

docker run --rm -v my-data-volume:/source -v $(pwd):/backup ubuntu tar cvf /backup/my-data-volume-backup.tar -C /source .

此命令:

  • 在容器中将我们的卷挂载到 /source
  • 在容器中将当前目录挂载到 /backup
  • 创建 /source 目录中所有内容的 tar 存档,并将其保存到 /backup/my-data-volume-backup.tar

验证是否创建了备份文件:

ls -lh my-data-volume-backup.tar

你应该看到类似这样的内容:

-rw-r--r-- 1 labex labex 10K Oct  1 12:34 my-data-volume-backup.tar

让我们检查备份文件的内容,以确保所有内容都已正确存档:

tar -tf my-data-volume-backup.tar

输出应包括:

./
./config/
./config/settings.conf
./important.txt
./test.txt

现在我们已经创建了卷的备份,我们准备好模拟将其迁移到新主机。

模拟将卷迁移到新主机

在现实世界中,你将使用 scprsync 或文件共享服务等工具将备份文件传输到新主机。对于本实验,我们将通过删除原始卷并创建一个新卷来恢复我们的数据,从而模拟迁移。

模拟新主机环境

首先,让我们清理旧容器,以模拟移动到新环境:

docker rm -f my-container data-generator

现在,让我们删除原始卷,以模拟在新主机上重新开始:

docker volume rm my-data-volume

创建一个新卷,它将代表我们在“新主机”上的卷:

docker volume create my-new-host-volume

从备份恢复卷

现在我们将把备份恢复到新卷:

docker run --rm -v my-new-host-volume:/destination -v $(pwd):/backup ubuntu bash -c "cd /destination && tar xvf /backup/my-data-volume-backup.tar"

此命令:

  • 创建一个临时容器
  • 将我们的新卷挂载到 /destination
  • 将当前目录(我们的备份所在位置)挂载到 /backup
  • 将 tar 存档解压缩到 /destination 目录

验证已恢复的数据

让我们验证所有数据是否已正确恢复到新卷:

docker run --rm -v my-new-host-volume:/data ubuntu ls -la /data

你应该看到与之前相同的文件结构:

total 12
drwxr-xr-x 3 root root 4096 Oct  1 12:34 .
drwxr-xr-x 1 root root 4096 Oct  1 12:34 ..
drwxr-xr-x 2 root root 4096 Oct  1 12:34 config
-rw-r--r-- 1 root root   21 Oct  1 12:34 important.txt
-rw-r--r-- 1 root root   24 Oct  1 12:34 test.txt

检查其中一个文件的内容,以确保数据完好无损:

docker run --rm -v my-new-host-volume:/data ubuntu cat /data/important.txt

输出:

This is important data

也检查配置文件:

docker run --rm -v my-new-host-volume:/data ubuntu cat /data/config/settings.conf

输出:

database_url=postgres://user:password@db:5432/mydb

将恢复的卷与新容器一起使用

现在我们已经成功“迁移”了我们的卷,让我们将其与新容器一起使用:

docker run --name my-new-container -v my-new-host-volume:/app/data -d nginx

这会创建一个新的 Nginx 容器,该容器将我们恢复的卷挂载到 /app/data

让我们验证容器是否可以访问卷数据:

docker exec my-new-container ls -la /app/data

你应该看到与之前相同的文件,确认迁移成功。

更新应用程序以使用新卷

在现实世界中,将卷迁移到新主机后,你需要更新你的 Docker Compose 文件或容器运行命令以使用新的卷名称或路径。例如,如果你使用 Docker Compose,你可能会按如下方式更新你的 docker-compose.yml 文件:

version: "3"
services:
  webapp:
    image: nginx
    volumes:
      - my-new-host-volume:/app/data
volumes:
  my-new-host-volume:
    external: true

这告诉 Docker 使用名为 my-new-host-volume 的外部创建的卷。

迁移过程现已完成!你已成功:

  1. 创建了一个 Docker 卷并向其中添加了数据
  2. 备份了卷数据
  3. 在模拟的“新主机”上创建了一个新卷
  4. 将备份数据恢复到新卷
  5. 验证了数据完整性
  6. 将新容器连接到已迁移的卷

最佳实践和高级迁移技术

现在你已经了解了 Docker 卷迁移的基础知识,让我们来探索一些最佳实践和高级技术,以使你的卷迁移更高效、更健壮。

规划卷迁移

在规划卷迁移时,请考虑以下因素:

  1. 卷大小:较大的卷传输时间更长,可能需要特殊处理。
  2. 停机时间要求:确定你的应用程序可以容忍的停机时间。
  3. 数据敏感性:确保敏感数据在传输过程中得到妥善保护。
  4. 网络带宽:考虑主机之间的可用带宽。

自动化迁移过程

对于频繁的迁移或多个卷的迁移,自动化可以节省时间并减少错误。让我们创建一个简单的 shell 脚本来自动化备份和恢复过程:

nano migrate-volume.sh

将以下内容添加到脚本中:

#!/bin/bash
## Simple Docker volume migration script

if [ $## -ne 2 ]; then
  echo "Usage: $0 <source_volume> <destination_volume>"
  exit 1
fi

SOURCE_VOLUME=$1
DEST_VOLUME=$2
BACKUP_FILE="/tmp/${SOURCE_VOLUME}-backup.tar"

echo "Creating backup of ${SOURCE_VOLUME}..."
docker run --rm -v ${SOURCE_VOLUME}:/source -v /tmp:/backup ubuntu tar cf /backup/${SOURCE_VOLUME}-backup.tar -C /source .

echo "Creating destination volume ${DEST_VOLUME}..."
docker volume create ${DEST_VOLUME}

echo "Restoring backup to ${DEST_VOLUME}..."
docker run --rm -v ${DEST_VOLUME}:/destination -v /tmp:/backup ubuntu bash -c "cd /destination && tar xf /backup/${SOURCE_VOLUME}-backup.tar"

echo "Migration complete. Verifying volume contents..."
docker run --rm -v ${DEST_VOLUME}:/data ubuntu ls -la /data

echo "Done!"

保存文件(Ctrl+O,然后 Enter)并退出(Ctrl+X)。

使脚本可执行:

chmod +x migrate-volume.sh

现在你可以使用一个命令来迁移卷:

./migrate-volume.sh my-new-host-volume another-volume

这将创建 my-new-host-volume 的备份,创建一个名为 another-volume 的新卷,并将备份恢复到其中。

处理大卷

对于大卷,基本的 tar 方法可能效率不高。这里有一些替代方案:

  1. 增量备份:仅传输自上次备份以来的更改。
  2. 压缩:使用压缩来减小备份文件的大小。
  3. 直接复制:使用 rsync 在主机之间直接复制。

让我们实现一种压缩备份方法:

docker run --rm -v my-new-host-volume:/source -v $(pwd):/backup ubuntu tar czf /backup/compressed-backup.tar.gz -C /source .

添加到 tar 命令中的 z 选项启用了压缩,从而生成了更小的备份文件。这对于文本密集型数据尤其有用。

从压缩备份恢复:

docker volume create compressed-volume
docker run --rm -v compressed-volume:/destination -v $(pwd):/backup ubuntu bash -c "cd /destination && tar xzf /backup/compressed-backup.tar.gz"

生产环境中的卷迁移

在生产环境中,你可能需要考虑以下附加方法:

  1. 存储驱动程序复制:一些存储驱动程序支持内置复制。
  2. Docker 卷插件:为你的存储系统使用专用插件。
  3. 数据库备份:对于数据库卷,使用数据库的原生备份工具。
  4. 计划迁移:使用 cron 等工具安排定期备份。

这标志着你 Docker 卷迁移之旅的结束。现在你已经掌握了在主机之间有效迁移 Docker 卷的知识和工具,确保在基础设施变更期间容器化应用程序的数据保持完整。

总结

在本实验中,你学习了如何在主机之间迁移 Docker 卷,这是管理容器化应用程序的一项基本技能。你获得了以下方面的实践经验:

  • 创建和管理 Docker 卷
  • 在 Docker 卷中添加和访问数据
  • 使用 tar 命令备份卷数据
  • 在新主机上恢复卷数据
  • 验证迁移后的数据完整性
  • 为卷迁移创建自动化脚本
  • 处理各种迁移场景,包括大卷

这些技能使你能够在环境之间移动容器、扩展你的基础设施或执行系统升级时保持数据连续性。Docker 卷迁移是一项基本操作,它使你能够自信地管理你的容器化应用程序,因为你知道你的持久数据可以根据需要安全可靠地传输。