> 文章列表 > Docker In Docker

Docker In Docker

Docker In Docker

Docker in Docker

适用场景

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

Docker In Docker

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

Docker in Docker ,以下简称 DinD

Docker In Docker

  • 如上图,可以在 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  COMMAND1 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/se64 root      0:02 containerd --config /var/run/docker/containerd/containerd.toml --log-level info221 root      0:00 sh244 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