【问题标题】:"a bind mount won't copy the container contents to the host automatically, unlike a named volume"“与命名卷不同,绑定挂载不会自动将容器内容复制到主机”
【发布时间】:2021-03-18 11:26:42
【问题描述】:

需要澄清评论here

绑定挂载的唯一“问题”是它不会复制 与命名卷不同,容器内容自动传输到主机。 docs.docker.com/compose/compose-file/#volumes

这是准确的吗?如果是,那么:

  1. 如何在使用bind mount 时将容器的“新数据”(例如不断增长的数据库)获取到主机中(以在容器重启的情况下持久化数据)?
  2. 在出现named volumes 之前,Docker 如何在容器重启时持久化数据?

【问题讨论】:

    标签: docker volume mount


    【解决方案1】:

    绑定挂载的唯一“问题”是它不会复制 与命名卷不同,容器内容自动传输到主机。

    这准确吗?

    接近准确,但我可以看到混乱。主机卷,也就是绑定挂载,没有来自 docker 的初始化功能。对于匿名卷和命名卷,docker 将使用该路径上的图像内容初始化卷。此初始化包括所有权和权限,这有助于避免权限错误。此初始化仅在创建容器且卷为新卷或空卷时运行,因此后续容器不会拾取对较新映像版本中所做的映像所做的更改。

    如果是,那么:

    1. 当使用绑定挂载(持久化数据)时,如何将容器的“新数据”(例如不断增长的数据库)获取到主机中 如果容器重启)?

    从容器中的应用程序读取和写入将按预期继续到绑定挂载中使用的主机文件系统。只是初始化步骤没有运行。

    1. 在有命名卷之前,Docker 如何在容器重启时持久化数据?

    有数据容器,从其他容器挂载卷,但这是不灵活的(所有卷路径都固定到数据容器中的路径),并且持久数据与临时容器的混合管理,因此已被逐步淘汰。

    卷用于处理容器之间的数据持久性。单个容器重新启动(而不是被替换)仍将具有所有容器特定的文件系统更改。 docker rm 命令会删除这些文件系统更改,以及容器日志和容器的元数据/配置。

    容器特定的更改是 docker 使用的覆盖文件系统的读/写顶层​​。卷挂载都是单独挂载到此覆盖文件系统的子目录中(就像/home/var 通常是 Linux 主机的 / 文件系统中的单独文件系统挂载一样,对这些其他路径的所有读取和写入都转到单独的底层文件系统)。

    【讨论】:

      【解决方案2】:

      如果您要将卷装载到容器中,并且希望该卷可靠地包含映像中的某些内容,则需要在容器启动时手动将其复制到那里。一种方法是使用入口点包装脚本:

      #!/bin/sh
      # Copy data into a possibly-mounted location
      cp -a /app/static /var/www
      # Then run the image's CMD
      exec "$@"
      

      你可以将它包含在你的镜像的 Dockerfile 中

      # Must use JSON-array syntax
      ENTRYPOINT ["/app/entrypoint.sh"]
      CMD same as it was before
      

      这里有两个关于 Docker 命名卷的初始化行为的重要细节需要注意。您注意到的第一个是 Docker 仅将内容复制到 Docker 命名卷的卷中;绑定挂载不会发生这种情况,在 Kubernetes 等其他环境中也不会发生。

      第二个更微妙的细节是初始化只在容器第一次运行时发生。如果您挂载到容器中的卷中已经有内容,它将隐藏已经存在的内容。在其他 SO 问题中,您可以看到此清单,例如,“我在我的节点 package.json 文件中添加了一个包,但是当我将 node_modules 目录放入卷中时,它会忽略更新”或“我是使用卷将内容导出到 nginx 代理,但没有更新”。

      【讨论】:

      • 感谢您的意见。然而,关于Docker only copies content into a volume for Docker named volumes; it doesn't happen for bind mounts,其他2 个答案是说Docker 确实将内容复制到bind mount。知道他们为什么会这样说吗?
      【解决方案3】:

      我认为@BMitch 接受的答案是正确的,但我会尝试添加一些细节以希望有用。

      这是准确的吗?如果是,那么:

      鉴于我的声明正在接受审查 - 我在这里完全遵从@BMitch :)! 不过我还要补充:

      当使用绑定挂载(在容器重启时持久化数据)时,如何将容器的“新数据”(例如不断增长的数据库)获取到主机中?

      主机卷命名卷都可以做到这一点。

      我认为争论的焦点是您希望在以下位置发生什么:

      • 容器的首次运行
      • 容器的后续运行
      • 卷在主机上的位置/可访问性系统。

      一旦将卷附加到容器(无论是命名卷还是绑定挂载),存储到该卷的任何内容都应在重新启动之间持久保存 - 这实际上是免费的。这假定相同的 docker-compose 配置,并且没有手动删除卷。

      以前使用 命名卷 会有点限制,因为您不能像使用绑定挂载 - 但问题似乎已经解决/现在可以解决了。

      绑定挂载能够在重启之间保持数据。我个人发现绑定卷在 99% 的时间里都在做我想做的事,也就是说,命名卷现在可以“做所有事情”,我会继续使用这些。

      虽然它们之间存在差异,但我敢肯定它们仍会偶尔咬人,需要他们联系实际专家,而不是像我这样的用户:)。

      【讨论】:

      • 谢谢。我个人喜欢bind mounts,因为它们是有形的。它们是系统上的文件夹。因此,如果需要备份数据,找到文件夹并进行备份是很容易的。对于named volumes,我担心在某些时候我可能会执行prune 并最终删除我忘记备份的孤立卷。它们只是没有那么有形和直观。
      • 这是一个很好的观点,我会更新我的回复以反映这一点
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-27
      • 2017-01-01
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      相关资源
      最近更新 更多