Docker容器完整启动流程(容器底层原理)
一、用户输入docker run命令
组件:docker CLI(客户端/上层工具)
1、解析用户输入的全部参数(镜像名称、-p 端口、挂载卷等)
2、通过REST API把请求发送给本地的dockerd守护进程
二、dockerd(Docker守护进程)接受请求
1、接收 CLI 发来的创建容器请求
2、处理上层资源逻辑:检查本地镜像,如果镜像不存在则执行docker pull拉取镜像;
3、创建网络、数据卷、端口映射规则(iptables DNAT 规则)
4、完成所有上层资源准备工作
5、通过 gRPC 协议调用底层containerd,下发 启动容器 任务
三、containerd容器引擎接收任务
1、containerd 是 Docker 底层容器生命周期管理器
2、收到 dockerd 请求后,不会直接调用 runc;
3、为这一个容器单独启动一个独立进程:containerd-shim-runc-v2
containerd是符合 OCI 标准的容器管理器,负责上层容器全生命周期管理:
--镜像管理(拉取、存储、删除镜像)
--容器生命周期调度(创建、启动、停止、删除容器)
--容器存储、网络管理
四、containerd-shim-runc-v2(垫片shim进程)
1、shim调用 runc 工具,发起容器创建
2、最重要价值:解耦容器进程 和 containerd 守护进程
如果没有 shim:一旦 containerd 进程重启 / 崩溃,所有容器都会被回收杀死
有 shim:containerd 重启,shim 继续运行,容器持续正常运行,不受影响
3、充当容器内进程的父进程
4、持续收集:容器退出状态、OOM 杀死事件、信号、标准输出日志,回传给 containerd
5、转发操作系统信号(docker stop、docker kill)下发给容器内部程序
containerd 启动容器时创建 containerd-shim 进程,shim 脱离 containerd 由 systemd 托管,实现进程生命周期解耦;containerd 重启时,shim 与容器持续运行;containerd 重启完成后,扫描现存 shim 并重新建立通信连接,恢复对容器的管理
五、runc(OCI 标准容器运行时)
1、runc是直接和 Linux 内核交互的工具,真正负责创建容器环境
2.、调用 Linux 内核系统调用:
Namespace:实现 PID、网络、挂载、用户等资源隔离
Cgroup:限制容器最大 CPU、内存、磁盘 IO 资源(你学习的内存限制、OOM 机制就在这里生效)
3、 挂载镜像文件系统(rootfs),组装容器运行环境
4、启动容器内部第一个主进程(容器 1 号进程)
六、Linux内核
Namespace:隔离容器,让容器看不见宿主机、其他容器资源
Cgroups:资源配额限制,触发内存上限时触发 OOM Killer
七、最终状态
runc退出,containerd-shim-runc-v2持续运行,持续托管容器内进程,整个容器正式运行。
问题:
重启 containerd 容器不死,为什么重启 docker 服务容器会停止?
解答:
containerd 依靠 containerd-shim 进程解耦容器生命周期,单独重启 containerd 不会终止容器; 而systemctl restart docker会重启 dockerd,dockerd 默认关闭时主动通知 containerd 停止所有容器;开启 live-restore 参数可以禁止 dockerd 停止容器。容器能否在 docker 重启后自动拉起,由容器--restart重启策略控制