Docker 容器中运行 Docker

567 阅读4分钟

docker官方镜像地址

使用场景

  • CI pipeline,在代码构建成功之后,需要在其中构建docker镜像并推送镜像
  • CI/CD pipelines
  • 沙盒环境

挂载docker.sock

1.png

什么是 /var/run/docker.sock:

/var/run/docker.sock是默认的 Unix 套接字,套接字用于同一主机上的进程之间的通信。

Docker 守护进程默认监听 docker.sock,如果在运行Docker守护程序的同一主机上,则可以使用 /var/run/docker.sock来管理容器。

例:在容器中执行以下命令将返回 docker 引擎的版本。

curl --unix-socket /var/run/docker.sock http://localhost/version

使用docker.sock实现docker in docker:

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

注意:这里我没指定docker的tag,默认拉取latest,请参照官方文档信息选择具体需要使用的镜像:docker官方镜像地址 现在,在容器中,您应该能够执行 docker 命令来构建镜像并将其推送到注册表。

宿主机执行docker version 的结果

对比下在宿主机和容器中执行docker version 的结果:

2.png 可以看到容器内客户端版本和宿主机镜像的客户端版本是不一致的,因为我拉的是latest,但是server是一致的,也就是说server都是连得宿主机上的server

在这里,实际的 docker 操作发生在运行基本 docker 容器的 VM 主机上,而不是在容器内。这意味着,即使在容器内执行 docker 命令,您也正在指示 docker 客户端通过以下方式连接到 VM 主机 docker-engine docker.sock

测试构建一个镜像

先拉取镜像:

docker pull docker

第 1 步:以交互模式启动 Docker 容器,挂载docker.sockas 卷。我们将使用官方的 docker 镜像:

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

第 2 步:进入容器后,执行以下 docker 命令:

docker pull nginx:1.14.2

第 3 步:查看刚刚拉取的镜像:

docker images | grep nginx

3.png 第 4 步:现在在测试目录中创建一个 Dockerfile:

mkdir test && cd test 
vi Dockerfile

复制以下 Dockerfile 内容以从容器内测试映像构建:

FROM nginx:1.14.2
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

第5步:构建 Dockerfile:

docker build -t nginx-test .

4.png

使用dind

5.png

此方法实际上在容器内创建了一个子容器。仅当希望在容器中包含容器和镜像时才使用此方法。否则,我建议您使用第一种方法。

为此,只需要使用带有dind标签的官方 docker 镜像。dind 映像是使用 Docker 在 docker 容器中运行所需的实用程序进行制作的。

注意:容器需要以特权模式运行。 先拉取镜像:

docker pull docker:dind

第 1 步:创建一个以 image 命名dind-test的docker:dind容器:

docker run --privileged -d --name dind-test docker:dind

第2步:使用exec进入容器:

docker exec -it dind-test /bin/sh

第 3 步:进入容器后,执行以下 docker 命令:

docker pull nginx:1.14.2

第 4 步:查看刚刚拉取的镜像:

docker images | grep nginx

6.png 这里和上面其实能看出区别了,上面执行这个命令还能看到一个其他tag的镜像,这里只能看到上一步拉取的镜像了(容器内的镜像和宿主机的镜像相对独立了,这也是dind和docker.sock的最大区别)。 第 5步:现在在测试目录中创建一个 Dockerfile:

mkdir test && cd test
vi Dockerfile

复制以下 Dockerfile 内容以从容器内测试映像构建:

FROM nginx:1.14.2
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

第6步:构建 Dockerfile:

docker build -t nginx-test .

使用 Sysbox Runtime

7.png

这是一种类似以沙箱的机制 由于在特权模式下运行基本容器,方法 1 和 2 在安全性方面存在一些缺点。Nestybox 试图通过一个 sysbox Docker 运行时来解决这个问题。

如果使用Nestybox sysbox 运行时创建容器,它可以在能够运行 systemd、docker、kubernetes的容器内创建虚拟环境,而无需对底层主机系统进行特权访问。

全面了解sysbox:github.com/nestybox/sy… 第1步:安装sysbox运行环境。参考:github.com/nestybox/sy… 第 2 步:一旦 sysbox 运行时可用,我们所要做的就是使用 sysbox 运行时标志启动 docker 容器,如下所示,这里我们使用的是官方的 docker dind 镜像:

docker run --runtime=sysbox-runc --name sysbox-dind -d docker:dind

第 3 步:现在对 sysbox-dind 容器进行 exec 会话:

docker exec -it sysbox-dind /bin/sh

下面就可以开始在容器里构建镜像了,步骤和上面差不多我在这就不赘述了。

Docker-in-Docker on Kubernetes

有兴趣的可以看下,这个我就不再继续深入了:applatix.com/case-docker…

常见问题解答

在 Docker 中运行 Docker 安全吗?

docker.sock使用和方法在 docker 中运行 dockerdind安全性较低,因为它对 docker 守护进程具有完全权限。

如何在 Jenkins 的 docker 中运行 docker?

可以使用 Jenkins 动态 docker 代理设置并将 docker.sock 挂载到代理容器,以从代理容器中执行 docker 命令。