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


当前回答

如果可能的话,应该尽量避免在Docker内部运行Docker(又名dind)。(资料来源如下。)相反,您希望为您的主容器设置一种方式来生成兄弟容器并与它们通信。

Jérôme Petazzoni——这个特性的作者使得Docker可以在Docker容器中运行——实际上写了一篇博文说不要这样做。他描述的用例与OP中需要在其他Docker容器中运行作业的CI Docker容器的确切用例相匹配。

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

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

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

[The] simplest way is to just expose the Docker socket to your CI container, by bind-mounting it with the -v flag. Simply put, when you start your CI container (Jenkins or other), instead of hacking something together with Docker-in-Docker, start it with: docker run -v /var/run/docker.sock:/var/run/docker.sock ... Now this container will have access to the Docker socket, and will therefore be able to start containers. Except that instead of starting "child" containers, it will start "sibling" containers.

其他回答

我之前回答过一个类似的问题,关于如何在Docker内部运行Docker容器。

To run docker inside docker is definitely possible. The main thing is that you run the outer container with extra privileges (starting with --privileged=true) and then install docker in that container. Check this blog post for more info: Docker-in-Docker. One potential use case for this is described in this entry. The blog describes how to build docker containers within a Jenkins docker container. However, Docker inside Docker it is not the recommended approach to solve this type of problems. Instead, the recommended approach is to create "sibling" containers as described in this post

因此,在Docker内部运行Docker被许多人认为是解决这类问题的一种很好的解决方案。现在的趋势是使用“兄弟”容器。更多信息请参见本页@predmijat的回答。

如果可能的话,应该尽量避免在Docker内部运行Docker(又名dind)。(资料来源如下。)相反,您希望为您的主容器设置一种方式来生成兄弟容器并与它们通信。

Jérôme Petazzoni——这个特性的作者使得Docker可以在Docker容器中运行——实际上写了一篇博文说不要这样做。他描述的用例与OP中需要在其他Docker容器中运行作业的CI Docker容器的确切用例相匹配。

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

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

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

[The] simplest way is to just expose the Docker socket to your CI container, by bind-mounting it with the -v flag. Simply put, when you start your CI container (Jenkins or other), instead of hacking something together with Docker-in-Docker, start it with: docker run -v /var/run/docker.sock:/var/run/docker.sock ... Now this container will have access to the Docker socket, and will therefore be able to start containers. Except that instead of starting "child" containers, it will start "sibling" containers.

是的,我们可以在docker中运行docker,我们需要附加unix套接字/var/run/docker。使用-v /var/run/docker. Sock:/var/run/docker. Sock, docker守护进程默认监听父docker的音量。 有时,docker守护进程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-in-Docker (DinD)是可以的,事实上Docker(公司)对此有一个官方的DinD形象。

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

使用兄弟容器运行Docker的替代解决方案(又名Docker-out- Docker或dod)不需要特权容器,但有一些缺点,因为你从一个不同于它运行的上下文中启动容器(即,你从容器内部启动容器,但它运行在主机级别,而不是容器内部)。

我写了一篇博客,描述了DinD和DooD的利弊。

说到这里,Nestybox(我刚刚创立的一家初创公司)正在研究一种解决方案,能够安全地运行真正的docker中docker(不使用特权容器)。你可以在www.nestybox.com上查看。

在过去的几天里,我也像你一样在容器中运行容器。浪费了很多时间。到目前为止,大多数人建议我做一些事情,比如使用docker的DIND镜像,这并不适用于我的情况,因为我需要主容器是Ubuntu OS,或者运行一些特权命令并将守护socket映射到容器中。(这对我来说从来都不管用)

The solution I found was to use Nestybox on my Ubuntu 20.04 system and it works best. Its also extremely simple to execute, provided your local system is ubuntu (which they support best), as the container runtime are specifically deigned for such application. It also has the most flexible options. The free edition of Nestybox is perhaps the best method as of Nov 2022. Highly recommends you to try it without bothering all the tedious setup other people suggest. They have many pre-constructed solutions to address such specific needs with a simple command line.

The Nestybox provide special runtime environment for newly created docker container, they also provides some ubuntu/common OS images with docker and systemd in built. Their goal is to make the main container function exactly the same as a virtual machine securely. You can literally ssh into your ubuntu main container as well without the ability to access anything in the main machine. From your main container you may create all kinds of containers like a normal local system does. That systemd is very important for you to setup docker conveniently inside the container.

执行sysbox的一个简单的常用命令:

    dock run --runtime=sysbox-runc -it any_image

如果你认为这是你想要的,你可以在他们的github上找到更多: https://github.com/nestybox/sysbox

快速链接到如何部署简单的sysbox运行时环境容器的说明:https://github.com/nestybox/sysbox/blob/master/docs/quickstart/README.md