我有两个 Docker 镜像,一个包含 pandoc
(将不同格式的文档转换为多种格式的实用程序)和另一个包含 pdflatex
的工具(来自 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 "$@"
}
因此,当 pandoc
调用 pdflatex
时,会启动一个容器并进行转换。
但是当使用这 2 个容器时,我如何给 pdflatex
命令起别名来模拟它在只有 pandoc
的容器上的存在?
我查看了 docker-compose
,因为我已经使用它来使 2 个容器通信(应用程序与数据库通信)。我什至想过从容器 A 到容器 B 调用 ssh
命令来调用 pdflatex
命令,但这绝对是 not the right solution .
最后,我还构建了一个包含 pandoc
+ pdflatex
的图像(因为这两个可执行文件在同一个图像上),但我真的想保留分开 2 张图片,因为它们可以被其他图片独立使用。
编辑:
暴露了一个类似的问题 here ,据我了解,提供的答案需要将 Docker 安装在容器 A 上,并且需要在主机和容器 A 之间进行 docker 套接字绑定(bind) (/var/run/docker.sock
)。我不认为这是最佳实践,似乎可以创建 security issues 的 hack .
最佳答案
您的问题有多种解决方案,我会让您选择最适合您的一种。它们在下面列出,从最干净到最丑陋(在我看来,以及通常遵循的最佳实践)。
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 张图片,pandoc
, pdflatex
, 和 pdflatex + pandoc
, 以满足您可能有的所有需求,但是您将拥有至少一个与其他 2 个没有以任何方式链接的图像(不能继承“ child ”图像),使其更难维护.
3。 my-pandoc-image
中的 Docker 客户端+ Docker socket 安装
这是您在帖子末尾提到的解决方案,它可能是调用其他容器化命令的最通用和直接的解决方案,而不是精确的 pandoc
用例+ pdflatex
考虑到。
只需将 docker 客户端添加到您的图像 my-pandoc-image
并在运行时使用 docker run -v /var/run/docker.sock:/var/run/docker.sock
将 Docker 套接字作为卷传递.如果您担心无法制作 pandoc
调用docker run ...
而不是 pdflatex
直接,只需添加一个名为 pdflatex
的糟糕包装器在 /usr/local/bin/
负责执行docker run
4。使用volumes-from获取二进制文件
这可能是我将在这里介绍的不太干净。您可以尝试获取 pandoc
pdflatex
中的二进制文件容器或 pdflatex
pandoc
中的二进制文件使用 --volumes-from
的容器将所有内容打包在自己的 Docker 镜像中。但老实说,它更像是一种胶带,而不是真正的解决方案。
结论
您可以选择最适合您需求的解决方案,但我建议前 2 个,强烈反对最后一个。
关于 docker : Can a container A call an executable located on an other container B?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43442276/