注册

Docker 与 containerd 的架构差异

要深入理解 Docker 与 containerd 的架构差异,首先需要明确二者的定位:Docker 是一套完整的容器平台(含构建、运行、分发等全流程工具),而 containerd 是一个专注于容器生命周期管理的底层运行时(最初是 Docker 内置组件,后独立为 CNCF 项目)。二者的架构设计围绕 “功能边界” 和 “模块化程度” 展开,以下从核心定位、架构分层、关键组件、交互流程四个维度进行对比分析。

一、核心定位与设计目标

架构差异的根源在于二者的定位不同,直接决定了功能范围和模块划分:

维度Dockercontainerd
核心定位一站式容器平台(Build, Ship, Run)轻量级容器运行时(专注于容器生命周期管理:启动、停止、销毁、资源隔离)
设计目标简化开发者体验,提供全流程工具链;兼顾单机开发与简单集群场景满足云原生环境的可扩展性、稳定性;支持多上层调度器(K8s、Swarm 等)
功能范围包含镜像构建(docker build)、镜像仓库(docker push/pull)、容器运行、网络 / 存储管理、UI 等仅负责镜像拉取、容器运行时管理、底层存储 / 网络对接;无镜像构建功能
依赖关系早期内置 containerd 作为底层运行时(Docker 1.11+),2020 年后逐步拆分可独立运行,也可作为 Docker、K8s(默认运行时)、Nomad 等的底层依赖

二、架构分层对比

二者均遵循 “分层解耦” 思想,但分层粒度和模块职责差异显著。Docker 架构更 “重”(含上层业务逻辑),containerd 更 “轻”(聚焦底层核心能力)。

1. Docker 架构(2020 年后拆分版)

Docker 经历了从 “单体架构” 到 “模块化拆分” 的演进(核心是将 containerd 独立,自身聚焦上层工具链),当前架构分为 4 层,自下而上分别是:

架构层核心组件 / 功能职责说明
1. 底层运行时层containerd、runc承接 Docker daemon 的指令,负责容器的实际创建、启动、资源隔离(依赖 runc 作为 OCI runtime)
2. Docker 守护进程层dockerdDocker 的核心守护进程,负责接收客户端(docker CLI)请求,协调下层组件(如调用 containerd 管理容器,调用 buildkit 构建镜像)
3. 工具链层BuildKit、Docker Registry Client、Docker Network/Volume Plugins- BuildKit:替代传统 docker build 后端,优化镜像构建效率;- 镜像客户端:处理 docker push/pull 与仓库交互;- 网络 / 存储插件:管理容器网络(如 bridge、overlay)和数据卷
4. 客户端层docker CLI(命令行工具)、Docker Desktop UI(桌面端)提供用户交互入口,将 docker run/build/pull 等命令转化为 HTTP 请求发送给 dockerd

2. containerd 架构(CNCF 标准化版)

containerd 架构更聚焦 “容器生命周期”,采用 5 层模块化设计,每层职责单一,可独立扩展,自下而上分别是:

架构层核心组件 / 功能职责说明
1. OCI 运行时层runc、crun(可选)遵循 OCI 规范(Open Container Initiative),负责创建 Linux 容器(如调用 clone() 系统调用实现 PID 隔离,挂载 cgroup 限制资源)
2. 容器执行层containerd-shim(垫片进程)- 解耦 containerd 与容器进程:即使 containerd 重启,容器也不会退出;- 收集容器日志、监控容器状态、转发信号(如 docker stop 对应 SIGTERM)
3. 核心服务层containerd 守护进程(containerd)containerd 的核心,通过 gRPC 提供 API 服务,包含 4 个核心模块:- Namespaces:实现多租户资源隔离;- Images:管理镜像(拉取、存储、解压);- Containers:管理容器元数据(配置、状态);- Tasks:管理容器进程(启动、停止、销毁)
4. 元数据存储层BoltDB(嵌入式 key-value 数据库)存储容器、镜像、命名空间等元数据,无需依赖外部数据库(如 MySQL),轻量且高效
5. 上层适配层CRI 插件(containerd-cri)、Docker API 兼容层- CRI 插件:将 containerd 的 gRPC API 转化为 K8s 要求的 CRI(Container Runtime Interface),使其成为 K8s 默认运行时;- Docker API 兼容层:支持部分 Docker 命令,确保与老系统兼容

三、关键组件差异

架构的核心差异体现在 “组件职责划分” 和 “功能依赖” 上,以下是最关键的组件对比:

组件 / 能力Dockercontainerd
核心守护进程dockerd(上层协调)+ containerd(底层运行时,需与 dockerd 配合)containerd(独立守护进程,直接对接 OCI 运行时,无需依赖其他进程)
镜像构建内置 BuildKit(或传统后端),支持 docker build 命令无镜像构建功能,需依赖外部工具(如 BuildKit、img)
容器进程隔离dockerd → containerd → containerd-shim → runc → 容器进程(4 层调用)containerd → containerd-shim → runc → 容器进程(3 层调用,更轻量)
元数据存储依赖本地文件系统(/var/lib/docker)+ 部分内存缓存内置 BoltDB(/var/lib/containerd),元数据管理更统一、高效
API 接口主要提供 HTTP API(供 docker CLI 调用),对下层暴露有限以 gRPC API 为主(更适合跨进程通信),提供细粒度接口(如镜像、容器、任务分别有独立 API)
上层调度器支持主要支持 Docker Swarm,对接 K8s 需额外配置(早期需 cri-dockerd 插件)原生支持 K8s(通过 containerd-cri 插件),也支持 Swarm、Nomad 等

四、容器启动流程对比

通过 “容器启动” 这一核心场景,可以直观看到二者的架构交互差异:

1. Docker 启动容器的流程(以 docker run ubuntu 为例)

  1. 用户交互:用户在终端执行 docker run ubuntu,docker CLI 将命令转化为 HTTP 请求,发送给本地的 dockerd 守护进程。
  1. dockerd 协调
    • 检查本地是否有 ubuntu 镜像:若无,调用 “镜像客户端” 从 Docker Hub 拉取镜像;
    • 拉取完成后,dockerd 向 containerd 发送 gRPC 请求,要求创建并启动容器。
  1. containerd 处理
    • containerd 接收请求后,创建容器元数据(存储到本地),并启动 containerd-shim 垫片进程;
    • containerd-shim 调用 runc,由 runc 遵循 OCI 规范创建容器进程(分配 PID、挂载 cgroup、设置网络 / 存储)。
  1. 状态反馈
    • containerd-shim 实时收集容器状态(如运行中、退出),反馈给 containerd;
    • containerd 将状态转发给 dockerd,最终由 docker CLI 输出给用户(如 docker ps 显示容器列表)。

2. containerd 启动容器的流程(以 ctr run ubuntu my-container 为例,ctr 是 containerd 自带 CLI)

  1. 用户交互:用户执行 ctr run ubuntu my-container,ctr 直接通过 gRPC 调用 containerd 守护进程。
  1. containerd 核心处理
    • 检查本地镜像:若无,直接调用内置的 “镜像模块” 从仓库拉取 ubuntu 镜像;
    • 创建容器元数据(存储到 BoltDB),并启动 containerd-shim 垫片进程。
  1. OCI 运行时启动容器
    • containerd-shim 调用 runc 创建容器进程,完成资源隔离和环境初始化;
    • 容器启动后,containerd-shim 持续监控容器状态,直接反馈给 containerd。
  1. 状态反馈:containerd 将容器状态通过 gRPC 返回给 ctr,用户终端显示启动结果。

五、总结:架构差异的核心影响

对比维度Dockercontainerd
轻量级重(含全流程工具,依赖多组件)轻(仅核心运行时,组件少、资源占用低)
扩展性弱(架构耦合度较高,难适配多调度器)强(模块化设计,原生支持 K8s 等调度器)
性能略低(多一层 dockerd 转发,资源消耗多)更高(直接对接 OCI 运行时,调用链短)
使用场景单机开发、测试、小型应用部署云原生集群(如 K8s 集群)、大规模容器管理
学习成本低(CLI 友好,文档丰富)高(需理解 gRPC、OCI 规范,适合运维 / 底层开发)

简言之:Docker 是 “面向开发者的容器平台”,架构围绕 “易用性” 和 “全流程” 设计;containerd 是 “面向云原生的底层运行时”,架构围绕 “轻量、可扩展、高兼容” 设计。在当前云原生生态中,containerd 已成为 K8s 的默认运行时,而 Docker 更多用于单机开发场景。


作者:bobz965
来源:juejin.cn/post/7544381073698848811

0 个评论

要回复文章请先登录注册