使用场景
- CI pipeline,在代码构建成功之后,需要在其中构建docker镜像并推送镜像
- CI/CD pipelines
- 沙盒环境
挂载docker.sock
什么是 /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 的结果:
可以看到容器内客户端版本和宿主机镜像的客户端版本是不一致的,因为我拉的是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
第 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 .
使用dind
此方法实际上在容器内创建了一个子容器。仅当希望在容器中包含容器和镜像时才使用此方法。否则,我建议您使用第一种方法。
为此,只需要使用带有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
这里和上面其实能看出区别了,上面执行这个命令还能看到一个其他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
这是一种类似以沙箱的机制 由于在特权模式下运行基本容器,方法 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 命令。