containerd不是Docker Daemon的替代品,而是其内部专注容器生命周期管理的核心引擎,负责接收gRPC请求、调用runc创建容器、通过shim托管进程、管理镜像与状态机,并支持可插拔OCI运行时。

Containerd 不是 Docker Daemon 的替代品,而是它内部真正执行容器生命周期管理的核心引擎。Docker Daemon(dockerd)本身更像一个高级协调者——负责 CLI 解析、镜像构建、网络配置、卷管理等用户可见功能;而所有与“容器启停删”“镜像拉取存取”“运行时调用”直接相关的底层操作,都由 containerd 承担。
Containerd 的核心职责边界:专注容器生命周期闭环
它不处理构建镜像(那是 buildkit 或 docker build 的事),也不直接暴露 HTTP API 给用户。它的价值在于提供稳定、标准化、可嵌入的生命周期控制能力:
- 接收来自 dockerd 的 gRPC 请求(如 “启动容器 A”),转化为具体动作
- 调用
runc创建/启停容器进程,并通过containerd-shim长期托管,确保即使 containerd 进程重启,容器仍持续运行 - 管理容器状态机:从
Created→Running→Stopped→Deleted,每个状态变更都持久化到 BoltDB 元数据存储中 - 统一处理镜像拉取、解压、层挂载,支持 OCI 和 Docker 格式镜像共存
Containerd 如何与 runc 协同完成实际运行
runc 是 OCI 规范的最小实现,只做一件事:根据 config.json 和 rootfs 创建一个符合 Linux 命名空间和 cgroups 约束的进程。Containerd 不直接 fork runc,而是通过以下链路驱动:
- Containerd 启动一个
containerd-shim进程,作为该容器的“代理守护者” - shim 调用 runc 执行
runc create/runc start等命令 - runc 创建容器后退出,shim 持续监听其 exit 状态并上报给 containerd
- 容器进程崩溃或被 kill,shim 捕获信号,更新 containerd 中的状态记录
Containerd 的生命周期操作对应哪些底层行为
理解这些映射,才能定位问题根源:
-
create:生成容器根文件系统(overlayfs mount)、写入 runtime spec(config.json)、在元数据库中标记为
Created,但不启动进程 -
start:shim 调用 runc start → 启动 init 进程 → 设置 cgroups 限额 → 注册健康检查(如果配置了)→ 状态切为
Running -
stop:向容器 init 进程发 SIGTERM,等待 grace period 后发 SIGKILL → shim 清理 cgroups 和 namespace → 状态切为
Stopped - delete:仅当状态为 Stopped 时允许;卸载 rootfs、删除元数据、清理网络命名空间 → 彻底释放资源
为什么说 containerd 是“可拔插”的运行时中枢
它不绑定 runc。只要符合 OCI Runtime Interface 规范,就能替换:
- 用
crun替代 runc,降低内存开销(尤其在边缘场景) - 接入
kata-runtime实现轻量级虚拟机隔离(强安全需求) - 通过
containerd config修改默认 runtime,无需改动 dockerd 或上层编排器
这种设计让 Kubernetes、Podman、nerdctl 等都能复用同一套 containerd 实例,也解释了为何 Docker Desktop 和云厂商托管服务越来越倾向直接部署 containerd 而非完整 Docker Engine。


















