2. 容器运行时基础:Docker 与 containerd 运行时架构对比

在自动化流水线中,容器运行时是事件监听与触发的核心执行层。理解 Docker 与 containerd 的架构差异,有助于精准设计事件源、Hook 挂载点以及触发链路。本章从组件分层、进程模型、事件机制三个维度进行对比。

2.1 架构演进:从单体到分层

Docker 1.11 之前采用单体运行时架构,所有容器操作由 dockerd 进程直接调用底层 Linux 系统接口。从 1.11 开始,Docker 引入 containerd 作为容器生命周期管理中间层,形成三层解耦架构:

  • Docker CLI / API:用户交互与编排入口。
  • dockerd:镜像构建、网络、存储卷、Swarm 编排等上层逻辑。
  • containerd:容器生命周期管理(创建、启动、停止、删除)、镜像拉取与存储。
  • runc:OCI 运行时规范实现,负责实际创建容器进程。
关键认知: containerd 是 Docker 生态中的核心组件,但也可以独立运行,被 Kubernetes 通过 CRI(Container Runtime Interface)直接调用。当前主流 Kubernetes 集群默认使用 containerd 作为运行时。

2.2 架构对比:Docker 与 containerd

以下表格从组件、进程模型、事件接口、适用场景四个维度进行对比:

对比维度 Docker 运行时 containerd 运行时
核心进程 dockerd(守护进程)+ containerd + containerd-shim + runc containerd(守护进程)+ containerd-shim + runc
组件数量 4 层(CLI → dockerd → containerd → runc) 3 层(ctr/CRI → containerd → runc)
事件接口 Docker Events API(/events 端点) containerd Event Service(gRPC + 命名空间隔离)
镜像管理 dockerd 负责镜像拉取、构建、推送 containerd 内置镜像拉取与快照管理
网络与存储 dockerd 通过 libnetwork 管理网络,通过 volume driver 管理存储 不直接管理网络与存储,由上层(Kubernetes 或 Docker)通过 CNI/CSI 接入
事件粒度 容器、镜像、网络、卷、插件等全量事件 容器生命周期事件(创建、启动、退出、删除)+ 任务事件
适用场景 开发环境、单机编排、Docker Compose、Swarm 生产级 Kubernetes 集群、边缘计算、嵌入式容器

2.3 进程模型与事件链路

下图展示了 Docker 与 containerd 在事件监听链路中的进程关系:

Docker 与 containerd 事件链路对比 Docker 与 containerd 事件链路对比 Docker 运行时 dockerd containerd containerd-shim runc (OCI) Docker Events API containerd 运行时 containerd containerd-shim runc (OCI) containerd Event Service dockerd 层移除 事件直接通过 gRPC 暴露 无 dockerd 中间转换
事件监听建议: 在 containerd 环境中,事件订阅通过 containerd.WithEventService() 客户端选项建立 gRPC 流式连接,事件类型包括 container/create、container/start、container/exit 等。Docker 环境则使用 docker events --filter 命令或 SDK 的 client.Events() 方法。

2.4 事件订阅方式对比

两种运行时的事件订阅在接口协议、过滤能力、性能表现上存在显著差异:

特性 Docker Events containerd Events
协议 HTTP Streaming(Chunked Transfer) gRPC Server-Side Streaming
事件格式 JSON 对象(含 Type、Action、Actor) protobuf 序列化(Event 结构体)
过滤方式 URL 参数:--filter 'event=start' gRPC 元数据 + 服务端过滤器
命名空间 无原生命名空间隔离 支持多命名空间(Kubernetes 按 Pod 隔离)
事件持久化 默认不持久化,断开后丢失 可配置事件存储后端(如 BoltDB)
订阅示例 curl -N --unix-socket /var/run/docker.sock http://v1.41/events ctr events 或 gRPC 客户端订阅

2.5 事件触发场景对比

在自动化流水线中,不同运行时的事件触发能力直接影响监听方案设计:

  • 容器启动事件:Docker 通过 start 动作触发;containerd 通过 container/start 主题触发。
  • 容器退出事件:Docker 通过 die 动作(含退出码);containerd 通过 container/exit 事件(含退出码与时间戳)。
  • 镜像拉取事件:Docker 通过 pull 动作;containerd 通过 images/create 事件。
  • 健康检查事件:Docker 通过 health_status 动作;containerd 不直接提供,需上层应用实现。
注意: containerd 的事件主题命名采用 <资源类型>/<动作> 格式(如 container/create、task/start),而 Docker 使用扁平化的动作名称(如 create、start)。在编写事件监听适配层时,需要做主题映射转换。

2.6 选择建议

根据流水线部署环境选择运行时:

环境类型 推荐运行时 理由
Kubernetes 集群(生产) containerd CRI 原生支持、事件命名空间隔离、资源占用更低
Docker Compose 开发环境 Docker 生态完善、调试方便、事件类型丰富
边缘计算 / IoT containerd 组件精简、内存占用小、适合资源受限设备
混合架构(K8s + 传统 Docker) 双运行时适配 事件监听层需要抽象统一接口,屏蔽底层差异