挂载 docker 容器的主机路径

Mount docker Host path to Container

我有一个关于 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 转换 /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>

容器被创建,运行s 并退出,但 /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.

你在这里提出的 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 绑定安装语法。


你可以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,可读写,与容器运行ning 作为根)。无论您使用哪种基于 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 方法将根本不起作用,因为您无法控制命名卷挂载的传播设置。

What is the best Practice for Accessing Host Data [...], and write Data in the Host filesystem [...]?

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