从 docker 内部运行 docker 可以吗?

Posted

技术标签:

【中文标题】从 docker 内部运行 docker 可以吗?【英文标题】:Is it ok to run docker from inside docker? 【发布时间】:2015-03-08 21:42:24 【问题描述】:

我在 Docker 容器中运行 Jenkins。我想知道 Jenkins 容器也可以作为 Docker 主机吗?我正在考虑的是从 Jenkins 内部为每个集成测试构建启动一个新的 docker 容器(以启动数据库、消息代理等)。因此,在集成测试完成后应该关闭容器。是否有理由避免以这种方式从另一个 docker 容器中运行 docker 容器?

【问题讨论】:

另一种可能性是将主机的 docker 套接字挂载为容器中的卷。这使您可以创建“兄弟”容器,并具有能够重用缓存的优势。 我发现当从主机使用 docker 套接字时,如果我想挂载外部卷,则需要设置相对于主机的卷路径,因为这是 docker 守护程序运行的位置.除非路径重合,否则相对于启动容器的容器设置它不一定有效。 【参考方案1】:

我之前在 how to run a Docker container inside Docker 上回答过类似的问题。

在 docker 内部运行 docker 绝对是可能的。主要是你run外部容器extra privileges(以--privileged=true开头)然后在那个容器中安装docker。

查看这篇博文了解更多信息:Docker-in-Docker。

this entry 中描述了这方面的一个潜在用例。该博客描述了如何在 Jenkins docker 容器中构建 docker 容器。

但是,Docker 内部的 Docker 并不是解决此类问题的推荐方法。相反,推荐的方法是将“兄弟”容器创建为described in this post

因此,在 Docker 中运行 Docker 被许多人认为是解决此类问题的一种很好的解决方案。现在,趋势是改用“兄弟”容器。请参阅the answer by @predmijat on this page 了解更多信息。

【讨论】:

请参阅下面关于在 docker 中避免使用 docker 的评论。【参考方案2】:

在 Docker 中运行 Docker(又名 dind)虽然可能,但应尽可能避免。 (下面提供了源代码。)相反,您希望为您的主容器设置一种方式来生成 sibling 容器并与之通信。

Jérôme Petazzoni——使 Docker 可以在 Docker 容器中运行的特性的作者——实际上是写了a blog post saying not to do it。他描述的用例与 OP 的 CI Docker 容器的确切用例相匹配,该容器需要在其他 Docker 容器中运行作业。

Petazzoni 列出了 dind 麻烦的两个原因:

    它不能很好地与 Linux 安全模块 (LSM) 配合。 它会在文件系统中造成不匹配,从而给在父容器中创建的容器带来问题。

从那篇博文中,他描述了以下替代方案,

[最简单的方法是通过使用-v 标志绑定挂载它,将 Docker 套接字公开给您的 CI 容器。

简单地说,当你启动你的 CI 容器(Jenkins 或其他)时,不要用 Docker-in-Docker 来破解一些东西,而是用以下方式启动它:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

现在这个容器将可以访问 Docker 套接字,因此能够启动容器。除了启动“子”容器之外,它将启动“兄弟”容器。

【讨论】:

如何在没有sudo的情况下运行docker命令?谢谢 您需要将用户添加到docker 组:sudo usermod -aG docker $USER。之后您需要重新登录。 如何从硬币容器内重新登录? windows 呢?我没有/var/run/docker.sock Jérôme Petazzoni 改变了他的观点(2020 年),因为有像 sysbox 这样的新工具可以让它更方便。他更新了反映这一点的答案中链接的博客文章。【参考方案3】:

运行 Docker-in-Docker (DinD) 是可以的,事实上 Docker(公司)为此有一个 official DinD image。

但需要注意的是,它需要一个特权容器,根据您的安全需求,这可能不是一个可行的替代方案。

使用同级容器(也称为 Docker-out-of-Docker 或 DooD)运行 Docker 的替代解决方案不需要特权容器,但由于您从与其运行的上下文不同的上下文(即,您从容器内启动容器,但它在主机级别运行,而不是在容器内)。

我写了一篇博客,描述了 DinD 与 DooD 的优缺点here。

话虽如此,Nestybox(我刚刚创立的一家初创公司)正在研究一种安全运行真正 Docker-in-Docker 的解决方案(不使用特权容器)。你可以在www.nestybox.com查看。

【讨论】:

【参考方案4】:

是的,我们可以在 docker 中运行 docker,我们需要使用 -v /var/run/docker.sock:/var/run/docker.sock 将 docker 守护进程默认侦听的 unix 套接字 /var/run/docker.sock 作为卷附加到父 docker。 有时,docker daemon socket 可能会出现权限问题,您可以为其编写sudo chmod 757 /var/run/docker.sock

而且它还需要在特权模式下运行 docker,所以命令是:

sudo chmod 757 /var/run/docker.sock

docker run --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -it ...

【讨论】:

以上是关于从 docker 内部运行 docker 可以吗?的主要内容,如果未能解决你的问题,请参考以下文章

一个请求会进入多个docker容器吗

如何确定进程是不是在 lxc/Docker 内部运行?

如何从 Docker 容器内部访问在 WSL2 上运行的服务?

Keycloak:从内部 docker 容器运行时令牌颁发者无效

我可以运行 Docker 映像的中间层吗?

无法从 docker 容器内部访问 datadog 代理