Docker Cli

供用户使用的命令行工具,负责请求 docker API 与 dockerd 交互,使得用户可以便捷友好的操作 docker。

Dockerd

监听 Docker API 请求,通过 containerd 管理 container 生命周期 dockerd 通过 unix、tcp、fd 三种类型方式来接收 API 请求。默认的 unix socket 创建在 /var/run/docker.sock,启动 dockerd 需要 root 权限或者 docker group 权限。 dockerd 在启动的时候会拉起 containerd,并与 containerd 保持通信。
  1. $ ps aux | grep dockerd
  2. /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Containerd

containerd 的主要职责是管理容器的生命周期,此外它还做:
  1. 镜像的 pull & push
  2. 管理 storage
  3. 运行容器的时候通过 runc,并附带上合适的参数
  4. 管理网络
containerd 包含一个暴露 gRPC API 的 daemon 服务,这些 API 比较底层,为了被更好层调用,或者基于此做扩展。Docker 有很好的分层机制,containerd 不会直接被用户使用, 自己也是通过 runc 去运行容器。

🐋[Docker] Docker 组件基本介绍 - 图1

containerd-architecture containerd 拥有很强的适配性,其已是事实上的工业标准。containerd 通过 UNIX socket 对外暴露 gRPC API 。通过 containerd 的启动命令,可以很轻易的找到 sokcet 文件的具体位置。
  1. $ ps aux | grep containerd
  2. root 19513 0.0 4.9 634988 93836 ? Ssl 2020 0:20 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

RunC

/usr/bin/docker-runc 可以视作 containerd 的一部分,它是一个运行遵从 OCI 标准容器的二进制工具。容器镜像通过 OCI 标准的格式打包,通常包括一个 config.json 文件和系统根目录。
  1. $ tree -L 2 .
  2. .
  3. ├── config.json
  4. └── rootfs
  5. ├── bin
  6. ├── boot
  7. ├── dev
  8. ├── docker-entrypoint.d
  9. ├── docker-entrypoint.sh
  10. ├── etc
  11. ├── home
  12. ├── lib
  13. ├── lib64
  14. ├── media
  15. ├── mnt
  16. ├── opt
  17. ├── proc
  18. ├── root
  19. ├── run
  20. ├── sbin
  21. ├── srv
  22. ├── sys
  23. ├── tmp
  24. ├── usr
  25. └── var
  26. 21 directories, 2 files
config.json 文件具体都记录了点什么呢?主要字段包括:
  1. ociVersion 遵从的 OCI 版本
  2. mounts 挂载信息
  3. linux 需要做隔离的 namespace

containerd-shim

containerd-shim 的存在使得 container 可以脱离 containerd 独立运行。(默认的,停掉 dockerd,container 也停止了,但可以通过 daemon.json 配置实现 dockerd 停掉后,container 照常运行。) 作为 container 的父进程,container-shim 主要负责如下职责:
  1. 使得 runc 运行完 container 后可以退出,无需为了一个 container 开启一个 runtime 常驻进程
  2. 保持容器的 stdio 开启状态,不至于容器写 stdio 后收到 SIGPIPE 而退出
  3. 把容器的 exit status 报告给 containerd

这些 docker 组件是如何协同工作的?

当我们启动 docker 后,dockerd 会默认拉起 containerd
  1. $ ps fxa | grep docker -A 3
  2. 52660 ? Ssl 0:01 /usr/bin/dockerd
  3. 52666 ? Ssl 0:01 \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
假使我们运行一个 container ,这时就会看到 containerd-shim
  1. $ docker run -d alpine sleep 60
  2. 643b5259637ced4c0c41a830034ebfe411aa1bdfac23b1c1f57926d3a9e552f0
  3. $ ps fxa | grep docker -A 3
  4. 52660 ? Ssl 0:01 /usr/bin/dockerd
  5. 52666 ? Ssl 0:01 \_ docker-containerd --config /var/run/docker/containerd/containerd.toml
  6. 54038 ? Sl 0:00 \_ docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/643b5259637ced4c0c41a830034ebfe411aa1bdfac23b1c1f57926d3a9e552f0 -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
  7. 54052 ? Ss 0:00 \_ sleep 60

调用顺序是 <font style="color:rgb(255, 93, 108);">dockerd --> containerd --> container-shim --> "sleep 60"</font>