如何在主机之间迁移 Docker 卷?

eri*_*mjl 14 docker docker-volume

Docker 的文档指出卷可以“迁移”——我假设这意味着我应该能够将卷从一台主机移动到另一台主机。(非常乐意在这一点上得到纠正。)但是,同一文档页面没有提供有关如何执行此操作的信息。

深入研究后,我发现了一个较旧的问题(大约 2015 年左右),它指出这是不可能的,但考虑到已经过去了 2 年,我想我会再问一次。

如果它有帮助的话,我正在开发一个 Flask 应用程序,它使用 [TinyDB] + 本地磁盘作为其数据存储 - 我已经确定我不需要比这更奇特的东西;目前这是一个为了学习而完成的项目,所以我决定变得非常轻量级。该项目的结构如下:

/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
Run Code Online (Sandbox Code Playgroud)

我的和data/*中有该文件夹,这样它们就不会受到版本控制,并且在构建映像时被 Docker 忽略。.dockerignore.gitignore

在开发应用程序时,我还尝试使用尽可能接近真实世界的数据库条目和 PDF,因此我在应用程序中植入了非常小的真实数据子集,这些数据存储在安装的卷上直接进入data/Docker 容器实例化时。

我想要做的是将容器部署在远程主机上,但让远程主机植入启动数据(理想情况下,这将是我在本地使用的卷,以最大程度地方便);稍后,随着更多数据添加到远程主机上,我希望能够将其拉回,以便在开发过程中我可以使用最终用户输入的最新数据。

环顾四周,我想做的“hacky”方式就是简单地使用rsync,这可能会很好。但是,如果我缺少解决方案,我将非常感谢指导!

Bos*_*rot 13

根据Docker 文档,您还可以创建备份并恢复它:

备份卷

docker run --rm --volumes-from CONTAINER -v \
$(pwd):/backup ubuntu tar cvf /backup/backup.tar /MOUNT_POINT_OF_VOLUME
Run Code Online (Sandbox Code Playgroud)

从另一台主机上的备份恢复卷

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"
Run Code Online (Sandbox Code Playgroud)

或者(我更喜欢)将其复制到本地存储

docker cp --archive CONTAINER:/MOUNT_POINT_OF_VOLUME ./LOCAL_FOLDER
Run Code Online (Sandbox Code Playgroud)

然后将其复制到其他主机并以例如开始

docker run -v ./LOCAL_FOLDER:/MOUNT_POINT_OF_VOLUME some_image
Run Code Online (Sandbox Code Playgroud)


Rob*_*ake 8

我处理此问题的方法是生成一个 Docker 容器,用于存储您想要在开发环境中播种的数据的副本。然后,您可以将该容器中的数据公开为卷,最后将该卷安装到您的开发容器中。我将用一个例子来演示:

创建数据容器

首先,我们将创建一个包含种子数据的 Docker 容器,仅此而已。我将创建一个Dockerfileat~/data/Dockerfile并为其提供以下内容:

FROM alpine:3.4
ADD . /data
VOLUME /data
CMD /bin/true
Run Code Online (Sandbox Code Playgroud)

然后您可以使用以下命令构建它:

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>
Run Code Online (Sandbox Code Playgroud)

我们在这里所做的首先是创建种子数据容器的实例。然后,我们创建开发容器的实例并将数据容器中的卷安装到其中。这意味着您将在/data开发容器中获取种子数据。

这会有点麻烦,您知道需要运行两个命令,因此我们可以继续使用 Docker Compose 等工具更好地编排它

使用 Docker Compose 进行简单编排

Docker Compose是一种同时运行多个容器的方法。您可以声明您的环境需要是什么样子并执行诸如定义之类的操作:

“我的开发容器取决于我的种子数据容器的实例”

您创建一个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
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用 立即启动所有容器docker-compose up -d my_app。Docker Compose 足够智能,可以首先启动数据容器的实例,然后最后启动应用程序容器。

在主机之间共享数据容器

最简单的方法是将数据容器作为映像推送到Docker Hub。构建镜像后,可以将其推送到 Docker Hub,如下所示:

docker push myproject/my-seed-data:latest

它在概念上与将 Git 提交推送到远程存储库非常相似,但在本例中您推送的是 Docker 映像。然而,这确实意味着任何环境现在都可以提取该映像并使用其中包含的数据。这意味着当你有新的种子数据时,你可以重新生成数据镜像,将其推送到标签下的 Docker Hub :latest,当你重新启动你的开发环境时将拥有最新的数据。

对我来说,这是共享数据的“Docker”方式,它使数据在 Docker 环境之间可移植。您还可以执行一些操作,例如通过 Jenkins 等 CI 环境中的作业定期生成数据容器。


has*_*.sd 5

你可以使用这个技巧:

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 - " '
Run Code Online (Sandbox Code Playgroud)

更多信息