Docker in Docker

适用场景

​ 在 CI 中,通常会有一个 CI Engine 负责解析流程,控制整个构建过程,而将真正的构建交给 Agent 去完成。例如,Jenkins 、GitLab 均是如此

同时 Agent 是动态的,构建时才需要,构建完成时即销毁。CI 非常适合实践容器、Serverless 等技术,因此在生产过程中 Agent 经常是容器化的

Docker in Docker ,以下简称 DinD

如上图,可以在 Container 中直接运行一个 Docker Daemon ,然后使用 Container 中的 Docker CLI 工具操作容器。 这种方式下,容器中的 Docker Daemon 完全独立于外部,具有良好的隔离特性。看起来,Container 类似一个 VM ,但 DinD 的作者自己也不是很推荐。主要原因还是安全问题。DinD 需要以特权模式启动,这种嵌套会带来潜在的安全风险。这种方式下,响应命令的容器嵌套于使用 docker 命令的容器 在docker容器内启动一个docker daemon,对外提供服务,每个运行中的容器,都是一个进程,这个进程都托管在docker daemon中,优点在于镜像和容器都在一个隔离的环境,保持宿主机的环境。

宿主机的docker.sock

/var/run/docker.sock是默认的Unix套接字。套接字用于在同一主机上的进程之间进行通信。 Docker守护程序默认情况下侦听docker.sock。 如果您在运行Docker守护程序的主机上,则可以使用/var/run/docker.sock管理容器 通过类似docker run -v /var/run/docker.sock:/var/run/docker.sock的命令将宿主机 docker.sock 文件挂载到容器, 并且直接挂载宿主机的/usr/bin/docker, 这样容器内就不需安装 Docker 程序 当容器内使用docker命令时,实际上调用的是宿主机的docker daemon和docker命令。也就是说,容器内实际并未运行 docker server,但是能够通过宿主机执行docker任务,从而实现轻量级 docker in docker。需要特别说明的是,真正执行 docker 命令的是跑在宿主机上的 docker-engine(服务器),因此这并不是真正的 "Docker in Docker" 如果您的容器可以访问docker.sock,则意味着它具有对docker守护程序的更多特权。因此,在实际项目中使用时,请了解并使用安全隐患。 因为容器的docker可以访问并删除宿主机的所有镜像

方式1:挂载主机上的docker.sock以及docker二进制文件

docker run -it \

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

-v $(which docker):/usr/bin/docker \

centos docker version

方式2:挂载主机docker.sock并在容器中安装docker客户端

[root@k8s-master-1 ~]# docker run -it -v /var/run/docker.sock:/var/run/docker.sock -v $(which docker):/usr/bin/docker centos:centos7 /bin/bash

[root@f3cd8d37aa6c /]# curl -o /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

[root@f3cd8d37aa6c /]# yum install -y docker-ce-cli

[root@f3cd8d37aa6c /]# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

d4aee13cdbda 0623d6874ffb "/coredns -conf /etc…" 22 minutes ago Up 22 minutes k8s_coredns_coredns-85b5646f88-4lmkv_kube-system_d19c99e3-fe1f-4202-8e5e-6fede07c9363_1

3e0435b049be registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 22 minutes ago Up 22 minutes k8s_POD_coredns-85b5646f88-4lmkv_kube-system_d19c99e3-fe1f-4202-8e5e-6fede07c9363_11

ab5e7d06f9ed 37c457685cef "/opt/bin/flanneld -…" 22 minutes ago Up 22 minutes k8s_kube-flannel_kube-flannel-ds-csxnw_kube-flannel_f3c2439a-d99b-4193-af55-c20da2444ddc_1

2572eba4255f registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 22 minutes ago Up 22 minutes k8s_POD_kube-flannel-ds-csxnw_kube-flannel_f3c2439a-d99b-4193-af55-c20da2444ddc_1

3f91f321d5f3 68cb0c05b3f2 "/bin/node_exporter …" 22 minutes ago Up 22 minutes k8s_node-exporter_monitor-prometheus-node-exporter-psppj_monitor_475de9d4-ee2a-426f-8673-2e020d5beab4_1

bfec55401ebb registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 22 minutes ago Up 22 minutes k8s_POD_monitor-prometheus-node-exporter-psppj_monitor_475de9d4-ee2a-426f-8673-2e020d5beab4_1

方式3:使用官方docker客户端

[root@k8s-master-1 ~]# docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

4bfabf7e08b8 docker "docker-entrypoint.s…" Less than a second ago Up Less than a second sweet_archimedes

d4aee13cdbda 0623d6874ffb "/coredns -conf /etc…" 24 minutes ago Up 24 minutes k8s_coredns_coredns-85b5646f88-4lmkv_kube-system_d19c99e3-fe1f-4202-8e5e-6fede07c9363_1

3e0435b049be registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 24 minutes ago Up 24 minutes k8s_POD_coredns-85b5646f88-4lmkv_kube-system_d19c99e3-fe1f-4202-8e5e-6fede07c9363_11

ab5e7d06f9ed 37c457685cef "/opt/bin/flanneld -…" 24 minutes ago Up 24 minutes k8s_kube-flannel_kube-flannel-ds-csxnw_kube-flannel_f3c2439a-d99b-4193-af55-c20da2444ddc_1

2572eba4255f registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 24 minutes ago Up 24 minutes k8s_POD_kube-flannel-ds-csxnw_kube-flannel_f3c2439a-d99b-4193-af55-c20da2444ddc_1

3f91f321d5f3 68cb0c05b3f2 "/bin/node_exporter …" 24 minutes ago Up 24 minutes k8s_node-exporter_monitor-prometheus-node-exporter-psppj_monitor_475de9d4-ee2a-426f-8673-2e020d5beab4_1

bfec55401ebb registry.aliyuncs.com/google_containers/pause:3.8 "/pause" 24 minutes ago Up 24 minutes k8s_POD_monitor-prometheus-node-exporter-psppj_monitor_475de9d4-ee2a-426f-8673-2e020d5beab4_1

docker:dind

此方法实际上在容器内部创建一个子容器。仅当确实要在容器中包含容器和镜像时才使用此方法。 否则,建议使用第一种方法。为此,只需要使用带有dind标签的官方docker镜像即可 先启动一个docker:dind容器A,再启动一个docker容器B,容器B指定host为A容器内的docker daemon docker dind方式有所不同,所有的docker操作真正在容器内部进行,包括创建的容器、拉取的镜像都保留在容器内部 docker in docker的原理是挂载cgroup、tmpfs、securityfs、cgroup的SUBSYS、关掉不需要的文件描述符、最后启动dockerd

官方提供了2种类型的docker in docker镜像

docker:latest 只包含docker客户端docker:dind 包含docker客户端和docker引擎

# 运行docker dind容器

[root@k8s-master-1 ~]# docker run --privileged --name docker-dind -d docker:dind

44c5bb4c3a943939b7fbc880ce2e5c27bba76ebca550600bc1a901a3359df876

[root@k8s-master-1 ~]# docker exec -it docker-dind sh

/ # docker image ls

REPOSITORY TAG IMAGE ID CREATED SIZE

/ # ps -ef

PID USER TIME COMMAND

1 root 0:00 dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376 --tlsverify --tlscacert /certs/server/ca.pem --tlscert /certs/server/cert.pem --tlskey /certs/se

64 root 0:02 containerd --config /var/run/docker/containerd/containerd.toml --log-level info

221 root 0:00 sh

244 root 0:00 ps -ef

# dind中运行容器

/ # docker run -it busybox sh

Unable to find image 'busybox:latest' locally

latest: Pulling from library/busybox

b50100f25006: Pull complete

Digest: sha256:b5d6fe0712636ceb7430189de28819e195e8966372edfc2d9409d79402a0dc16

Status: Downloaded newer image for busybox:latest

/ #

/ # docker ps -a

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

8a78a61c5e91 busybox "sh" 25 seconds ago Exited (0) 5 seconds ago funny_feistel

参考文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。