docker主要组件
- docker cli(dockerd)
- docker daemon(dockerd)
- containerd
- containerd-shim
- RunC
docker创建并且运行一个容器的过程
-
容器镜像的下载是由dockerd完成的,但容器的创建和运行就需要containerd(docker-containerd) 来完成了。Dockerd与docker-containerd之间是通过grpc协议通信的。
-
当docker-containerd收到dockerd 启动容器的请求之后,会做一些初始化工作,然后启动docker-containerd-shim进程,并将相关配置作为参数传给它。
docker-containerd负责管理所有本机正在运行的容器,而一个docker-containerd-shim进程只负责管理一个运行的容器
-
docker-containerd-shim相当于docker-runc的一个封装,充当docker-containerd和docker-runc之间的桥梁,docker-runc能干的就交给docker-runc来做,docker-runc做不了的就放到这里来做
docker主要进程以及之间的父子关系
docker run -d busybox sleep 100000
systemd
├─dockerd─┬─containerd─┬─containerd-shim─┬─sleep
│ │ │ └─10*[{containerd-shim}]
docker-runc进程
- 容器启动的过程中,docker-runc作为dockerd-contained-shim的子进程存在,docker-runc进程根据容器的配置找到容器的rootfs为容器创建bash进程后,就退出了,创建的第一个bash进程有父进程dockerd-contained-shim接管
- runc是标准化的产物,为了防止一家商业公司主导容器化标准,因此又了opencontainers组织,因此,创建容器,其实最终通过runc就可以了。
- 如果要自己编译,就要先克隆代码,然后执行 sudo make install。
git clone http://github.com/opencontainers/runc
make install
- 用runc创建一个容器
mkdir -p mycontainer/rootfs
cd mycontainer/
docker export $(docker create busybox) | tar -C rootfs -xf -
runc spec
runc run mycontainer
- 源码 Runc源码阅读
containerd
架构
- Containerd对上提供grpc接口方式的api,而Metric api是度量功能使用的。所有的编排工具容器适配层都可以使用grpc api作为containerd的客户端,使用containerd操作容器。
- Distribution用于容器镜像的pull和push动作(这部分出现在Containerd中完全是因为OCI v1标准推出Docker公司将自己镜像格式贡献了出去,所以containerd理所当然需要对镜像进行管理了)。
- Bundle(在docker的语景里是容器运行的目录集)子系统用于容器存储管理它的作用就是原来的graphdriver,它提供将容器镜像拆解成容器运行时刻需要的Bundle。
- Runtime子系统用于容器执行和监控,就是它直接操作runtime,传递和接收信号(signal),中转fifo,记录日志。
- Content、Metadata和Snapshots是存储管理组组件
- Excutor和Supervisor是执行体组件。 整个系统通过Event事件驱动。
源码
docker-containerd-shim
-
允许runc在创建&运行容器之后退出
-
用shim作为容器的父进程,而不是直接用containerd作为容器的父进程,是为了防止这种情况:当containerd挂掉的时候,shim还在,因此可以保证容器打开的文件描述符不会被关掉
-
依靠shim来收集&报告容器的退出状态,这样就不需要containerd来wait子进程
前两点尤其重要,有了它们就可以在不中断容器运行的情况下升级或重启 dockerd(这对于生产环境来说意义重大)
第一点,为什么要允许runc退出呢? 因为,Go编译出来的二进制文件,默认是静态链接,因此,如果一个机器上起N个容器,那么就会占用M*N的内存,其中M是一个runc所消耗的内存。 但是出于上面描述的原因又不想直接让containerd来做容器的父进程,因此,就需要一个比runc占内存更小的东西来作父进程,也就是shim。
docker-proxy
容器网络代理
#docker ps
e7ea6abc29cf goharbor/harbor-log:v1.8.3 "/bin/sh -c /usr/loc…" 3 months ago Up 3 months (healthy) 127.0.0.1:1514->10514/tcp harbor-log
#pstree -l -a -A
├─dockerd -H fd:// --containerd=/run/containerd/containerd.sock
│ ├─docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 1514 -container-ip 172.19.0.2 -container-port 10514
#iptables-save |grep 1514
-A DOCKER -d 127.0.0.1/32 ! -i br-a4c38bc30ca1 -p tcp -m tcp --dport 1514 -j DNAT --to-destination 172.19.0.2:10514