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

时间:2017-08-16 13:08:27

标签: docker flask docker-volume

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

在SO上挖掘,我发现了一个older问题(大约在2015-ish),表明这是不可能的,但考虑到它已经过去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

我的data/*.dockerignore中有.gitignore文件夹,因此它们不受版本控制,在构建图像时会被Docker忽略。

在开发应用程序时,我也尝试使用尽可能接近真实世界的数据库条目和PDF,因此我在应用程序中添加了一小部分真实数据,这些数据存储在卷上在实例化Docker容器时直接挂载到data/

我想要做的是将容器部署在远程主机上,但让远程主机接种起始数据(理想情况下,这将是我本地使用的卷,为了方便起见);随着更多数据被添加到远程主机上,我希望能够将其拉回来,以便在开发期间我使用最终用户输入的最新数据。

环顾四周,我正在考虑的“hacky”方式就是使用rsync,这可能会很好。但是,如果我找不到解决方案,我非常感谢指导!

2 个答案:

答案 0 :(得分:2)

我接近这个的方法是生成一个Docker容器,该容器存储要为您的开发环境设定种子的数据的副本。然后,您可以将该容器中的数据公开为卷,最后将该卷装入开发容器中。我将用一个例子来证明:

创建数据容器

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

FROM alpine:3.4
ADD . /data
VOLUME /data
CMD /bin/true

然后你可以用:

构建它

docker build -t myproject/my-seed-data .

这会创建一个标记为myproject/my-seed-data:latest的Docker镜像。图像只包含您要为环境设定种子的所有数据,存储在图像中的/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这样的东西更好地编排它

使用Docker撰写的简单业务流程

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

然后,您可以使用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环境中的作业定期生成数据容器之类的事情。

答案 1 :(得分:1)

您可以使用此技巧:

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 - " '

more information