【问题标题】:Mount docker Host path to Container将 docker 主机路径挂载到容器
【发布时间】:2025-12-14 15:00:02
【问题描述】:

我有一个关于 Docker 的问题。我正在运行一个 Docker:dind 容器,我通过 API 对其进行控制。我正在使用以下命令调用 Dind 容器

docker run --network some_network --prvileged -e DOCKER_TLS_CERTDIR= -d -p 2375:2375 -p 2376:2376 -v TransformationData:/mnt docker:dind

通过命名卷,我的数据进入 /mnt 目录中的 Dind 容器。

现在变得棘手了。我想通过 API 运行一个容器,该 API 转换 /mnt 目录中的数据并将转换后的数据保存在同一目录中,因此我可以通过命名卷使用它。以下是 API 调用

<REQUEST OPERATION="POST" URL="/containers/create" CONTENT-TYPE="application/json">
     <CONTENT>
        {
            "Image":        "citygml4j/citygml-tools",
            "AttachStdin":  true,
            "HostConfig": {"Binds": [
                            "/mnt:/data[[r]shared, [rw]]"
                    ]}} ,
            "Cmd":[
            "to-cityjson",
            "/data"
            ]            
        }
     </CONTENT>
  </REQUEST>

<REQUEST OPERATION="POST" CONTENT-TYPE="application/json">
        <xsl:attribute name="URL">/containers/<xsl:value-of select="substring(//CONTENT,11, 7)" />/start</xsl:attribute>
        <CONTENT>{}</CONTENT>
    </REQUEST>

容器被创建、运行和退出,但 /mnt 目录中的数据保持不变。而不是“绑定”配置,我还尝试了具有相同结果的“挂载”配置。

此问题的一个可能原因是 citygml-tools 容器对主机的 /mnt 目录没有写入权限。我试图用特权标签来解决这个问题,但没有奏效。 “绑定”中的 [[r]shared, [rw]] 部分也应该允许写入,但它也不起作用。

令人讨厌的部分是,citygml-tools 容器没有提供任何错误消息或 Lo 文件,所以我在尝试时实际上并不知道发生了什么。现在只是试错之类的事情......

长话短说:从容器访问主机数据并从容器将数据写入主机文件系统的最佳实践是什么?

关于 citygml-tools 的其他信息:

https://github.com/citygml4j/citygml-tools#:~:text=citygml-tools%20is%20a%20command%20line%20utility%20that%20bundles,is%20licensed%20under%20the%20Apache%20License%2C%20Version%202.0.

【问题讨论】:

  • 您在docker run 命令中拼错了“特权”
  • 如果目标是读写主机文件,可以直接在主机上运行进程吗?您是否需要中间的 Docker-in-Docker 层(这会显着增加复杂性,而且有点不寻常)?
  • @DavidMaze 我正在从另一个容器开始转换容器——它正在与 API 通信——我想避免将主机套接字直接安装到该容器,因此使用了中间的 Dind 容器。但是如果没有解决方案这样做,安装主机套接字也应该是可能的。

标签: docker host volume mount


【解决方案1】:

您在这里提出的 DinD 设置特别复杂,我会避免使用它。如果可能的话,我什至会避免在这里启动额外的容器。

在实际的 API 请求中,我怀疑您的标点符号过多。 Docker CLI 和 API 文档使用方括号对名称的可选部分进行分组和指示; [r]shared 表示“sharedrshared”。在 API ContainerCreate 操作中,"HostConfig": {"Binds: []}" 选项包括带有两个或三个冒号分隔部分的字符串,/host/path:/container/path:optionsoptions 是逗号分隔的选项列表,:options 部分是可选的。所以你可能需要

{
  "HostConfig": {
    "Binds": [
      "/mnt:/data:rw"
    ]
  }
}

完全没有方括号。

您的 DinD 设置正在将主机 Docker 中的命名卷挂载到 DinD 容器的 /mnt 目录中,然后您的 API 请求正在尝试挂载它。这通常不会创建可直接访问的主机文件,您可能还需要更改 DinD 容器以使用 -v /host:/container bind-mount 语法。


您可以use citygml-tools as a (Java) library。如果您的应用程序是基于 JVM 的,那么这样做可以避免您在此处显示的所有复杂性。将包含数据的主机目录绑定挂载到您的应用程序容器中,并删除所有 Docker API 设置。

如果您不能这样做,您还可以将 JVM 和 citygml-tools 版本安装到您​​的 Docker 映像本身中。完成此操作后,您可以将citygml-tools to-cityjson 之类的命令作为普通子进程运行,而无需涉及 Docker。同样,将主机目录绑定挂载到应用程序容器中。

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install --no-install-recommends --assume-yes \
      curl \
      openjdk-11-jre-headless \
      unzip
RUN cd /usr/local \
 && curl -LO https://github.com/citygml4j/citygml-tools/releases/download/v1.4.2/citygml-tools-1.4.2.zip \
 && unzip citygml-tools-1.4.2.zip \
 && rm citygml-tools-1.4.2.zip

如果您需要保留 Docker API 路径,更简单的选择是跳过 DinD 容器并直接与主机的 Docker 套接字通信。这被认为是不安全的,但正是因为它可以逃脱 Docker 容器并将主机上的任意文件挂载到新容器中(甚至是主机的 /etc,读写,容器以 root 身份运行)。无论您使用哪种基于 XML 的工具来发出请求,都需要知道如何向 Unix 套接字发出 HTTP 请求。 (不要启用对主机 Docker 套接字的 TCP 访问。)

docker run ... \
  -v /var/run/docker.sock:/var/run/docker.sock \
  your-image
# without a DinD container

您可能在使用bind propagation 时遇到了一些问题,因为您正尝试在另一个上下文中重新挂载一个挂载点。我认为这不适用(您是直接挂载挂载点,而不是尝试挂载额外的文件系统作为挂载点的子目录)。但是,如果确实如此,那么这种 DinD 方法将根本不起作用,因为您无法控制命名卷挂载的传播设置。

访问主机数据 [...] 并将数据写入主机文件系统 [...] 的最佳实践是什么?

直接在主机上运行该进程。这不需要升级权限即可运行,它遵循正常的主机文件系统权限,并且通常更容易开发和测试应用程序。如果您正在考虑像 Kubernetes 这样的集群环境,它们实际上根本无法访问“主机数据”(如果您的集群有 100 个节点,这就是“主机”?),您将需要一些其他存储机制。

【讨论】:

  • 嗨,大卫,感谢您提供的全面解答!将此工具箱用作 Java 库对于我的用例来说是不可能的。我尝试安装主机,但我不太确定如何将 Http 请求发送到 Unix 套接字。我的工具需要一个 URL。我尝试使用var/run/docker.sock,但没有奏效。可能是个愚蠢的主意,但我没有更好的办法。
  • 我按照您指定的方式连接了套接字。当我检查我的容器时,绑定看起来像这样:“Type”:“bind”,“Source”:“/run/host-services/docker.proxy.sock”,“Destination”:“/var/run/docker .sock", "Mode": "", "RW": true, "Propagation": "rprivate" 我仍然无法连接到套接字。还有更多我需要指定/考虑的吗?如何向 unix 套接字发送 http 请求?
最近更新 更多