如何在构建 tool/utility 时从另一个容器中 运行 一个容器
How to run a container from within another container when building a tool/utility
我们已经开始在创建工具和实用程序时使用容器,因此各个开发人员不必费心安装先决条件。效果很好,如:
docker run --rm -v $PWD/input.yaml:/input.yaml our.registry.com/dev/toolA /input.yaml
直到 toolA
需要调用另一个实用程序,toolB
,它也包装在一个容器中。
是否有一种从容器中 运行 容器的通用方法,以便它与 docker、podman 或任何没有 [= 的 container-tech-du-jour 一起工作13=] 的调用者必须添加“可怕的”额外参数,例如--privileged=true
或 -v /var/run/docker.sock:/var/run/docker.sock
?
我知道可以 运行 docker-in-docker,显然也可以 运行 , but that is not recommended。添加 -v /var/run/docker.sock:/var/run/docker.sock
是推荐的方法,但那只是 docker,对吧?
否则这是一个有漏洞的抽象。目前,我通过在 toolA
中包含 toolB
容器的基本位来构建 toolA
,使 toolA
对 toolB
实施中的变化敏感,我'我想避免。或者我可以构建 toolA
但仅支持 docker 并要求用户添加 -v /var/run/docker.sock:/var/run/docker.sock
参数 :-(.
是否有更优雅的方法从 toolA
的容器内部调用 toolB
的容器,它适用于所有常见的容器技术,并且在启动时不需要额外的参数 toolA
?
从容器内部 运行 容器的方法是非正统的,可以通过重新设计流程来避免。它会起作用,但会产生巨大的复杂性和开销。
如果您只是在构建期间需要该工具,则可以使用多阶段构建。您需要做的是创建一个通常称为 builder
的基础容器,其中包含构建所需的所有工具,在基础容器中获取项目并 运行 构建。构建完成后,您将进入下一阶段并创建一个基础 运行ner,您将在其中仅安装 运行time 环境所需的库和模块,并从 builder
到 运行 容器。
这样,您将可以完全控制 build-time
和 run-time
环境。此外,如果您有多个项目或复杂的构建,您可以将多阶段构建与 buildx 结合使用,以 运行 并行构建。
Is there a generic way to run a container from within a container [...] without having to add "scary" extra parameters like [...] -v /var/run/docker.sock:/var/run/docker.sock?
没有
(您必须挂载主机的 Docker 套接字;调用容器不需要 --privileged
;一旦调用容器可以访问套接字,您就不能限制它可以做什么,因此它可以自己启动特权容器,或启动容器绑定安装主机的 /etc
目录,或以其他方式做一些顽皮的事情。我实际上不确定这如何与 Podman 交互。)
特别是如果容器需要写回主机系统,docker run
命令很难紧凑。您将需要一个 -u
选项来指定主机用户 ID,-v
选项用于 Docker 套接字和当前目录,--rm
以及存储库名称,全部为开销,每次你 运行 命令。我可能更喜欢使用本地命令,也许是使用广泛可用的脚本语言,如 Python 或 Bourne shell.
如果您仍然想从容器中 运行 这个,您可以 COPY
或以其他方式将工具 B 安装到同一容器中,这样您就可以进行正常的子进程调用来启动它;或者将工具 B 分解为库和应用程序,并将库包含在工具 A 中(类似于您现在正在做的事情,但更正式)。
从安全角度来看,将 -v /var/run/docker.sock:/var/run/docker.sock
传递给外部容器是有问题的,因为它授予外部容器对主机上 运行 容器的权限。恶意外部容器可以 运行 具有绑定挂载的此类容器,以便可以写入主机目录。
运行 使用 Podman 作为普通用户(无根用户)使用 --privileged
的外部容器可以保护您免受这种情况的影响。外部容器将只能写入您作为绑定挂载传入的目录(例如,使用 -v
命令行选项)。
--privileged
标志的含义在Red Hat article中有解释。
2021 年 6 月更新。在 Podman 中 运行ning Podman 时,不再需要传递 --privileged
标志。请参阅 中的示例
和 Red Hat 博客 post How to use Podman inside of a container
我们已经开始在创建工具和实用程序时使用容器,因此各个开发人员不必费心安装先决条件。效果很好,如:
docker run --rm -v $PWD/input.yaml:/input.yaml our.registry.com/dev/toolA /input.yaml
直到 toolA
需要调用另一个实用程序,toolB
,它也包装在一个容器中。
是否有一种从容器中 运行 容器的通用方法,以便它与 docker、podman 或任何没有 [= 的 container-tech-du-jour 一起工作13=] 的调用者必须添加“可怕的”额外参数,例如--privileged=true
或 -v /var/run/docker.sock:/var/run/docker.sock
?
我知道可以 运行 docker-in-docker,显然也可以 运行 -v /var/run/docker.sock:/var/run/docker.sock
是推荐的方法,但那只是 docker,对吧?
否则这是一个有漏洞的抽象。目前,我通过在 toolA
中包含 toolB
容器的基本位来构建 toolA
,使 toolA
对 toolB
实施中的变化敏感,我'我想避免。或者我可以构建 toolA
但仅支持 docker 并要求用户添加 -v /var/run/docker.sock:/var/run/docker.sock
参数 :-(.
是否有更优雅的方法从 toolA
的容器内部调用 toolB
的容器,它适用于所有常见的容器技术,并且在启动时不需要额外的参数 toolA
?
从容器内部 运行 容器的方法是非正统的,可以通过重新设计流程来避免。它会起作用,但会产生巨大的复杂性和开销。
如果您只是在构建期间需要该工具,则可以使用多阶段构建。您需要做的是创建一个通常称为 builder
的基础容器,其中包含构建所需的所有工具,在基础容器中获取项目并 运行 构建。构建完成后,您将进入下一阶段并创建一个基础 运行ner,您将在其中仅安装 运行time 环境所需的库和模块,并从 builder
到 运行 容器。
这样,您将可以完全控制 build-time
和 run-time
环境。此外,如果您有多个项目或复杂的构建,您可以将多阶段构建与 buildx 结合使用,以 运行 并行构建。
Is there a generic way to run a container from within a container [...] without having to add "scary" extra parameters like [...] -v /var/run/docker.sock:/var/run/docker.sock?
没有
(您必须挂载主机的 Docker 套接字;调用容器不需要 --privileged
;一旦调用容器可以访问套接字,您就不能限制它可以做什么,因此它可以自己启动特权容器,或启动容器绑定安装主机的 /etc
目录,或以其他方式做一些顽皮的事情。我实际上不确定这如何与 Podman 交互。)
特别是如果容器需要写回主机系统,docker run
命令很难紧凑。您将需要一个 -u
选项来指定主机用户 ID,-v
选项用于 Docker 套接字和当前目录,--rm
以及存储库名称,全部为开销,每次你 运行 命令。我可能更喜欢使用本地命令,也许是使用广泛可用的脚本语言,如 Python 或 Bourne shell.
如果您仍然想从容器中 运行 这个,您可以 COPY
或以其他方式将工具 B 安装到同一容器中,这样您就可以进行正常的子进程调用来启动它;或者将工具 B 分解为库和应用程序,并将库包含在工具 A 中(类似于您现在正在做的事情,但更正式)。
从安全角度来看,将 -v /var/run/docker.sock:/var/run/docker.sock
传递给外部容器是有问题的,因为它授予外部容器对主机上 运行 容器的权限。恶意外部容器可以 运行 具有绑定挂载的此类容器,以便可以写入主机目录。
运行 使用 Podman 作为普通用户(无根用户)使用 --privileged
的外部容器可以保护您免受这种情况的影响。外部容器将只能写入您作为绑定挂载传入的目录(例如,使用 -v
命令行选项)。
--privileged
标志的含义在Red Hat article中有解释。
2021 年 6 月更新。在 Podman 中 运行ning Podman 时,不再需要传递 --privileged
标志。请参阅