Docker : 容器 A 可以调用位于另一个容器 B 上的可执行文件吗?

Docker : Can a container A call an executable located on an other container B?

我有两张 Docker 图片,一张包含 pandoc (an utility to convert documents in different formats to many formats), and an other containing pdflatex (from texlive,用于将 tex 文件转换为 pdf)。我的目标是将文档从 md 转换为 pdf.

我可以 运行 每张图片分开 :

# call pandoc inside my-pandoc-image (md -> tex)
docker run --rm \
    -v $(pwd):/pandoc \
    my-pandoc-image \
    pandoc -s test.md -o test.tex

# call pdflatex inside my-texlive-image (tex -> pdf)
docker run --rm \
    -v $(pwd):/texlive \
    my-texlive-image \
    pdflatex test.tex # generates test.pdf

但是,其实我想要的是直接调用pandoc(从它的容器中)将md转换成pdf,像这样:

docker run --rm \
    -v $(pwd):/pandoc \
    my-pandoc-image \
    pandoc -s test.md --latex-engine pdflatex -o test.pdf

此命令在这里不起作用,因为容器内的 pandoc 试图调用 pdflatex(必须在 $PATH 中)来生成 pdf,但是 pdflatex 不存在,因为它没有安装在 my-pandoc-image.

在我的例子中,pdflatex 安装在映像 my-texlive-image 中。

因此,根据这个示例,我的问题是:容器 A 可以调用位于另一个容器 B 上的可执行文件吗?

我很确定这是可能的,因为如果我在主机上安装 pandoc (没有 pdflatex),我可以 运行 pandoc -s test.md--latex-engine=pdflatex -o test.pdf 通过简单地将 pdflatex 命令别名化为 :

pdflatex() {
    docker run --rm \
        -v $(pwd):/texlive \
        my-texlive-image \
        pdflatex "$@"
}

因此,当 pdflatexpandoc 调用时,容器启动并进行转换。

但是当使用这两个容器时,我如何为 pdflatex 命令设置别名来模拟它在只有 pandoc 的容器上的存在?

我看了一下 docker-compose,因为我已经用它使 2 个容器通信(应用程序与数据库通信)。我什至想过 ssh-ing 从容器 A 到容器 B 来调用 pdflatex 命令,但这绝对是 not the right solution.

最后,我还构建了一个包含 pandoc + pdflatex 的图像(之所以有效,是因为两个可执行文件在同一个图像上),但我真的想将这两个图像分开,因为它们可以被其他图像独立使用。

编辑:

暴露了类似的问题here, as I understand the provided answer needs Docker to be installed on container A, and needs a docker socket binding (/var/run/docker.sock) between host and container A. I don't think this is best practice, it seems like a hack that can create security issues

您的问题有多种解决方案,我会让您选择最适合您的一种。它们如下所示,从最干净到最丑陋(在我看来以及通常遵循的最佳实践)。

1。使其成为一项服务

如果您最终经常调用它,可能值得将 pandoc 作为 (HTTP) API 公开。有些图片已经这样做了,例如 metal3d/pandoc-server(我已经成功使用过它,但我相信你可以找到其他图片)。

在这种情况下,您只需 运行 一个包含 pandoc + pdflatex 一次 的容器就可以了!

2。使用图像继承!

制作2张图片:一张只带pandoc,另一张带pandoc + pdflatex继承第一张带FROM指令在Dockerfile.

它将解决您对大小的担忧,并且仍然能够 运行 pandoc 而无需获取 pdflatex。然后,如果您需要使用 pdflatex 拉取图像,它只是 一个额外的层 ,而不是整个图像。

你也可以用另一种方式,使用一个基本图像 pdflatex 和另一个添加 pandoc 如果你发现自己经常单独使用 pdflatex 图像并且很少使用pandoc 图像没有 pdflatex。您还可以制作 3 张图像,pandocpdflatexpdflatex + pandoc,以满足您可能拥有的所有需求,但是您将至少有一张未链接的图像对其他 2 个的任何方式(无法继承 "child" 图像),使其更难维护。

3。 Docker my-pandoc-image 中的客户端 + Docker 套接字挂载

这是您在 post 末尾提到的解决方案,这可能是调用其他容器化命令的最通用和直接的解决方案,而不是考虑到 pandoc + pdflatex 的精确用例。

只需将 docker 客户端添加到您的映像 my-pandoc-image 并在 运行 时间使用 docker run -v /var/run/docker.sock:/var/run/docker.sock 将 Docker 套接字作为音量传递。如果您担心无法使 pandoc 调用 docker run ... 而不是直接调用 pdflatex,只需在 /usr/local/bin/ 中添加一个名为 pdflatex 的糟糕包装器即可将负责做 docker run

4。使用 volumes-from 获取二进制文件

这可能是我将在这里展示的不太干净。您可以尝试在 pdflatex 容器中获取 pandoc 二进制文件,或者在 pandoc 容器中获取 pdflatex 二进制文件,使用 --volumes-from 将所有内容打包在自己的 Docker 图片。但老实说,它更像是胶带而不是真正的解决方案。

结论

您可以选择最适合您需要的解决方案,但我会建议前 2 个,强烈反对最后一个。