如何在主机之间迁移 Docker 卷?
How to migrate Docker volume between hosts?
Docker 的 documentation 声明卷可以是 "migrated" - 我假设这意味着我应该能够将卷从一台主机移动到另一台主机。 (很高兴在这一点上得到纠正。)但是,同一文档页面没有提供有关如何执行此操作的信息。
深入研究 SO,我发现了一个 问题(大约 2015 年左右),它指出这是不可能的,但考虑到它已经过去 2 年了,我想我会再问一遍。
如果有帮助,我正在开发一个使用 [TinyDB] + 本地磁盘作为其数据存储的 Flask 应用程序 - 我确定我不需要比这更花哨的东西;这是目前为学习而完成的项目,所以我决定非常轻量级。该项目的结构如下:
/project_directory
|- /app
|- __init__.py
|- ...
|- run.py # assumes `data/databases/ and data/files/` are present
|- Dockerfile
|- data/
|- databases/
|- db1.json
|- db2.json
|- files/
|- file1.pdf
|- file2.pdf
我的 .dockerignore
和 .gitignore
中有文件夹 data/*
,因此它们不在版本控制之下,并且在构建图像时被 Docker 忽略.
在开发应用程序时,我还尝试使用尽可能接近真实世界的数据库条目和 PDF,因此我在应用程序中植入了非常小的真实数据子集,这些数据存储在实例化 Docker 容器时直接装入 data/
的卷。
我想做的是将容器部署到远程主机上,但为远程主机播种启动数据(理想情况下,这将是我一直在本地使用的卷,以提供最大的便利);稍后在远程主机上添加更多数据时,我希望能够将其拉回,以便在开发过程中我可以使用最终用户输入的最新数据。
环顾四周,我想做的 "hacky" 方法就是简单地使用 rsync
,这可能会很好。但是,如果有我遗漏的解决方案,我将不胜感激指导!
我采用的方法是生成一个 Docker 容器,用于存储要用于播种开发环境的数据副本。然后,您可以将该容器中的数据公开为一个卷,最后将该卷装载到您的开发容器中。我将举例说明:
创建数据容器
首先,我们将创建一个 Docker 容器,其中仅包含您的种子数据。我会在 ~/data/Dockerfile
处创建一个 Dockerfile
并为其提供以下内容:
FROM alpine:3.4
ADD . /data
VOLUME /data
CMD /bin/true
然后您可以使用以下方法构建它:
docker build -t myproject/my-seed-data .
这将为您创建一个 Docker 标记为 myproject/my-seed-data:latest
的图像。该图像仅包含您想要为环境播种的所有数据,存储在图像内的 /data
处。每当我们将图像实例创建为容器时,它会将 /data
中的所有文件作为一个卷公开。
正在将卷装入另一个 Docker 容器
我想你 运行 宁你的 Docker 容器是这样的:
docker run -d -v $(pwd)/data:/data your-container-image <start_up_command>
您现在可以扩展它来执行以下操作:
docker run -d --name seed-data myproject/my-seed-data
docker run -d --volumes-from seed-data your-container-image <start_up_command>
我们在这里所做的是首先创建您的种子数据容器的实例。然后我们创建开发容器的实例并将数据容器中的卷安装到其中。这意味着您将在开发容器中的 /data
处获得种子数据。
这有点麻烦,您知道需要 运行 两个命令,因此我们可以继续使用 Docker Compose[=27= 之类的东西更好地编排它]
使用 Docker Compose 的简单编排
Docker Compose 是一种 运行 同时安装多个容器的方法。您可以声明您的环境需要的外观并执行诸如 define:
之类的操作
"My development container depends on an instance of my seed data container"
您创建一个 docker-compose.yml
文件来布置您需要的内容。它看起来像这样:
version: 2
services:
seed-data:
image: myproject/my-seed-data:latest
my_app:
build: .
volumes_from:
- seed-data
depends_on:
- seed-data
然后您可以使用 docker-compose up -d my_app
一次启动所有容器。 Docker Compose 足够聪明,可以首先启动您的数据容器实例,然后最后启动您的应用程序容器。
在主机之间共享数据容器
最简单的方法是将数据容器作为图像推送到 Docker Hub。构建映像后,可以将其推送到 Docker Hub,如下所示:
docker push myproject/my-seed-data:latest
它在概念上与将 Git 提交推送到远程存储库非常相似,在这种情况下,您推送的是 Docker 图像。然而,这意味着任何环境现在都可以拉取此映像并使用其中包含的数据。这意味着当您有新的种子数据时,您可以重新生成数据图像,将其推送到 :latest
标签下的 Docker Hub,当您重新启动您的开发环境时,将拥有最新的数据。
对我来说,这是共享数据的 "Docker" 方式,它使数据在 Docker 环境之间保持可移植性。你也可以做一些事情,比如让你的数据容器在像 Jenkins 这样的 CI 环境中由作业定期生成。
你可以使用这个技巧:
docker run --rm -v <SOURCE_DATA_VOLUME_NAME>:/from alpine ash -c "cd /from ; tar -cf - . " | ssh <TARGET_HOST> 'docker run --rm -i -v <TARGET_DATA_VOLUME_NAME>:/to alpine ash -c "cd /to ; tar -xpvf - " '
根据 Docker docs 您还可以创建一个备份并恢复它:
备份量
docker run --rm --volumes-from CONTAINER -v \
$(pwd):/backup ubuntu tar cvf /backup/backup.tar /MOUNT_POINT_OF_VOLUME
从另一台主机上的备份恢复卷
docker run --rm --volumes-from CONTAINER -v \
$(pwd):/LOCAL_FOLDER ubuntu bash -c "cd /MOUNT_POINT_OF_VOLUME && \
tar xvf /backup/backup.tar --strip 1"
或(我更喜欢)将其复制到本地存储
docker cp CONTAINER:/MOUNT_POINT_OF_VOLUME ./LOCAL_FOLDER
然后将其复制到其他主机并从例如
开始
docker run -v ./LOCAL_FOLDER:/MOUNT_POINT_OF_VOLUME some_image
Docker 的 documentation 声明卷可以是 "migrated" - 我假设这意味着我应该能够将卷从一台主机移动到另一台主机。 (很高兴在这一点上得到纠正。)但是,同一文档页面没有提供有关如何执行此操作的信息。
深入研究 SO,我发现了一个
如果有帮助,我正在开发一个使用 [TinyDB] + 本地磁盘作为其数据存储的 Flask 应用程序 - 我确定我不需要比这更花哨的东西;这是目前为学习而完成的项目,所以我决定非常轻量级。该项目的结构如下:
/project_directory
|- /app
|- __init__.py
|- ...
|- run.py # assumes `data/databases/ and data/files/` are present
|- Dockerfile
|- data/
|- databases/
|- db1.json
|- db2.json
|- files/
|- file1.pdf
|- file2.pdf
我的 .dockerignore
和 .gitignore
中有文件夹 data/*
,因此它们不在版本控制之下,并且在构建图像时被 Docker 忽略.
在开发应用程序时,我还尝试使用尽可能接近真实世界的数据库条目和 PDF,因此我在应用程序中植入了非常小的真实数据子集,这些数据存储在实例化 Docker 容器时直接装入 data/
的卷。
我想做的是将容器部署到远程主机上,但为远程主机播种启动数据(理想情况下,这将是我一直在本地使用的卷,以提供最大的便利);稍后在远程主机上添加更多数据时,我希望能够将其拉回,以便在开发过程中我可以使用最终用户输入的最新数据。
环顾四周,我想做的 "hacky" 方法就是简单地使用 rsync
,这可能会很好。但是,如果有我遗漏的解决方案,我将不胜感激指导!
我采用的方法是生成一个 Docker 容器,用于存储要用于播种开发环境的数据副本。然后,您可以将该容器中的数据公开为一个卷,最后将该卷装载到您的开发容器中。我将举例说明:
创建数据容器
首先,我们将创建一个 Docker 容器,其中仅包含您的种子数据。我会在 ~/data/Dockerfile
处创建一个 Dockerfile
并为其提供以下内容:
FROM alpine:3.4
ADD . /data
VOLUME /data
CMD /bin/true
然后您可以使用以下方法构建它:
docker build -t myproject/my-seed-data .
这将为您创建一个 Docker 标记为 myproject/my-seed-data:latest
的图像。该图像仅包含您想要为环境播种的所有数据,存储在图像内的 /data
处。每当我们将图像实例创建为容器时,它会将 /data
中的所有文件作为一个卷公开。
正在将卷装入另一个 Docker 容器
我想你 运行 宁你的 Docker 容器是这样的:
docker run -d -v $(pwd)/data:/data your-container-image <start_up_command>
您现在可以扩展它来执行以下操作:
docker run -d --name seed-data myproject/my-seed-data
docker run -d --volumes-from seed-data your-container-image <start_up_command>
我们在这里所做的是首先创建您的种子数据容器的实例。然后我们创建开发容器的实例并将数据容器中的卷安装到其中。这意味着您将在开发容器中的 /data
处获得种子数据。
这有点麻烦,您知道需要 运行 两个命令,因此我们可以继续使用 Docker Compose[=27= 之类的东西更好地编排它]
使用 Docker Compose 的简单编排
Docker Compose 是一种 运行 同时安装多个容器的方法。您可以声明您的环境需要的外观并执行诸如 define:
之类的操作"My development container depends on an instance of my seed data container"
您创建一个 docker-compose.yml
文件来布置您需要的内容。它看起来像这样:
version: 2
services:
seed-data:
image: myproject/my-seed-data:latest
my_app:
build: .
volumes_from:
- seed-data
depends_on:
- seed-data
然后您可以使用 docker-compose up -d my_app
一次启动所有容器。 Docker Compose 足够聪明,可以首先启动您的数据容器实例,然后最后启动您的应用程序容器。
在主机之间共享数据容器
最简单的方法是将数据容器作为图像推送到 Docker Hub。构建映像后,可以将其推送到 Docker Hub,如下所示:
docker push myproject/my-seed-data:latest
它在概念上与将 Git 提交推送到远程存储库非常相似,在这种情况下,您推送的是 Docker 图像。然而,这意味着任何环境现在都可以拉取此映像并使用其中包含的数据。这意味着当您有新的种子数据时,您可以重新生成数据图像,将其推送到 :latest
标签下的 Docker Hub,当您重新启动您的开发环境时,将拥有最新的数据。
对我来说,这是共享数据的 "Docker" 方式,它使数据在 Docker 环境之间保持可移植性。你也可以做一些事情,比如让你的数据容器在像 Jenkins 这样的 CI 环境中由作业定期生成。
你可以使用这个技巧:
docker run --rm -v <SOURCE_DATA_VOLUME_NAME>:/from alpine ash -c "cd /from ; tar -cf - . " | ssh <TARGET_HOST> 'docker run --rm -i -v <TARGET_DATA_VOLUME_NAME>:/to alpine ash -c "cd /to ; tar -xpvf - " '
根据 Docker docs 您还可以创建一个备份并恢复它:
备份量
docker run --rm --volumes-from CONTAINER -v \
$(pwd):/backup ubuntu tar cvf /backup/backup.tar /MOUNT_POINT_OF_VOLUME
从另一台主机上的备份恢复卷
docker run --rm --volumes-from CONTAINER -v \
$(pwd):/LOCAL_FOLDER ubuntu bash -c "cd /MOUNT_POINT_OF_VOLUME && \
tar xvf /backup/backup.tar --strip 1"
或(我更喜欢)将其复制到本地存储
docker cp CONTAINER:/MOUNT_POINT_OF_VOLUME ./LOCAL_FOLDER
然后将其复制到其他主机并从例如
开始docker run -v ./LOCAL_FOLDER:/MOUNT_POINT_OF_VOLUME some_image