Docker 与 containerd 的架构差异

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

一、核心定位与设计目标

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

维度 Docker containerd
核心定位 一站式容器平台(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 守护进程层 dockerd Docker 的核心守护进程,负责接收客户端(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 命令,确保与老系统兼容

三、关键组件差异

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

组件 / 能力 Docker containerd
核心守护进程 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,用户终端显示启动结果。

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

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

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

相关推荐
小猪咪piggy1 小时前
【JavaEE】(20) Spring Boot 统一功能处理
java·spring boot·后端
bobz9659 小时前
ubuntu install NVIDIA Container Toolkit
后端
绝无仅有9 小时前
Go Timer 面试指南:常见问题及答案解析
后端·算法·架构
绝无仅有9 小时前
Go 语言面试指南:常见问题及答案解析
后端·面试·go
bobz9659 小时前
containerd (管理) 和 runc (执行)分离
后端
程序猿阿伟10 小时前
《跳出“技术堆砌”陷阱,构建可演进的软件系统》
后端
就叫飞六吧10 小时前
基于Spring Boot的短信平台平滑切换设计方案
java·spring boot·后端
bobz96511 小时前
NVIDIA Container Toolkit(容器运行时依赖)
后端
bobz96511 小时前
NVIDIA Container Toolkit 架构上下文
后端