在 docker 中从 docker 安装卷绑定?

Kru*_*lur 7 docker

我有一个 Docker 容器“A”,它将启动另一个容器“B”(通过卷挂载 /var/run/docker.sock)。现在,这些容器需要共享文件。

容器“B”期望文件被卷挂载,最简单的方法是将挂载从“A”绑定到“B”,但 Docker 不能这样做(绑定挂载总是来自主机文件系统)。

有没有一种简单的方法让容器与其创建的容器共享文件,而无需依赖主机文件系统,也无需从“A”构建“B”映像?

我一直在尝试创建卷并将文件复制到其中,但解决方案往往既复杂又脆弱。理想情况下,我想将解决方案放在 docker-compose 文件中,以便在“A”内运行,但这看起来几乎是不可能的。

作为参考,这是另一个可以完美解决我的问题的想法:https : //github.com/docker/compose/issues/3593#issuecomment-272089143

BMi*_*tch 10

当您挂载 docker 套接字时,它实际上并不是 docker 中的 docker,而只是一个客户端通过 API 向主机上的守护程序发出请求,而该守护程序不知道请求来自何处。因此,您可以将这个问题简化为“您能否将文件从一个容器挂载到另一个容器中”。不幸的是,如果不使用两个容器外部的卷,就没有简单的答案。这是因为容器文件系统依赖于用于组装各种图像和容器层的图形驱动程序,因此即使可能适用于 overlay2 的解决方案也会在其他驱动程序上中断,并且它将依赖于 docker 的内部结构,该内部结构可能会在没有警告的情况下发生变化.

进入外部卷后,我可以想到几种可能的解决方案。

选项A:公共主机目录。我经常将它与我认为笔记本电脑上的透明容器一起使用,隐藏了我在容器内运行命令的事实。我在容器中安装了一个带有完整路径的公共目录,例如-v $HOME:$HOME. 如果您在容器“A”和“B”中安装了相同的主机目录,则可以在容器“A”和“B”内部使用相同的技术。如果您对容器“A”使用上述卷挂载,这将适用于撰写文件,因为容器内的路径与主机上的路径相同。

选项 B:volumes_from。我什至不愿提及这个选项,因为随着用户采用群模式,它正在逐步淘汰,但是有一个选项可以将容器“A”中的所有卷安装到容器“B”。这仍然需要您在容器“A”中定义一个卷,但现在您不必关心卷的来源,它可以是主机、命名或匿名卷。

选项 C:共享命名卷。命名卷让 docker 管理数据的存储,默认情况下在主机上的 /var/lib/docker/volumes 下。您可以使用相同的命名卷运行两个容器,这允许您在容器之间传递数据。您确实需要具有容器“A”中卷的名称才能为具有相同名称的容器“B”运行命令。当您第一次使用命名卷时,命名卷还会从映像初始化命名卷的内容,因此这可能是有益的,尤其是对于文件所有权和权限。请注意,下次使用同名卷时,它不会重新初始化任何现有数据,而是之前的数据将是持久的。对于撰写文件,您需要将命名卷定义为外部卷。

选项 D:手动创建命名卷。如果您只是想将一些文件从容器“A”注入容器“B”,则有多种方法可以通过 docker API 将其注入。我已经看到文件保存到“A”上的环境变量中,然后环境变量写回到“B”入口点中的文件中。对于较大的文件,或为了避免更改“B”的入口点,您可以创建一个命名卷并通过将数据通过 docker 的 stdin/stdout 管道传递到正在运行的容器,然后使用 tar 打包/解包该数据以发送来填充它I/O 管道。这将在容器“A”内部工作,因为 tar 命令的一半在该容器的文件系统内运行。然后容器“B”将挂载该命名卷。

tar -cC source_dir . | \
  docker run --rm -i -v target_vol:/target busybox tar -xC /target
Run Code Online (Sandbox Code Playgroud)

为了从命名卷中取回数据,过程是相反的:

docker run --rm -v source_vol:/source busybox tar -cC /source . | \
  tar -xC target_dir
Run Code Online (Sandbox Code Playgroud)

与选项 C 类似,您需要在撰写文件中将此命名卷定义为外部卷。