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