docker采用c/s架构,客户端(docker cli)发送指令,守护进程(dockerd)协调containerd、runc、shim等组件完成镜像拉取、容器创建与运行,底层依赖namespaces隔离和cgroups资源限制。

学 Docker 架构原理与核心组件,关键不是死记命令,而是理清“谁在做什么、怎么协作、为什么这么设计”。从用户输入一条 docker run 开始,到容器真正跑起来,背后是一整套分层协作机制。抓主线、看交互、联系 Linux 底层,才能真正吃透。
先搞懂 C/S 架构这个骨架
Docker 本质是客户端-服务器模型,所有操作都围绕这个分工展开:
- 客户端(docker CLI)只负责发指令——它不运行容器,也不管理镜像,就像你用手机点外卖,只下单不炒菜;
- 守护进程(dockerd)才是真正的执行中枢——它监听 API 请求,协调 containerd、网络、存储等子系统;
- 客户端和 dockerd 可以在同一台机器,也能远程通信(比如用
DOCKER_HOST连集群节点),这点对理解 DevOps 流水线很重要。
拆解五大核心组件的职责链
一条 docker run nginx 命令,会依次触发以下组件协同工作:
- dockerd 接收请求,检查本地是否有 nginx 镜像,没有就去 registry 拉取;
- containerd 负责镜像解压、准备 rootfs、调用 runc 启动容器进程;
-
runc 是 OCI 标准实现,真正调用
clone()、setns()等系统调用,创建 namespace 和 cgroups; - containerd-shim 在容器启动后“接班”:保持容器进程存活、转发日志和信号、隔离 dockerd 与容器生命周期;
- 镜像本身不是单个文件,而是由多层只读层 + 一层可写层构成(UnionFS),每层对应 Dockerfile 中的一条指令,复用率高、构建快。
必须关联 Linux 内核两大基石
脱离内核谈容器,就像讲汽车不提发动机。两个概念必须动手验证:
-
Namespaces 提供“视图隔离”:用
ls /proc/[pid]/ns/查看某容器进程的 pid、net、mnt 等 namespace 是否独立; -
cgroups 实现“资源限制”:进容器里执行
cat /sys/fs/cgroup/memory/memory.limit_in_bytes,就能看到内存上限是否生效; - 可以手动用
unshare和cgroup v2模拟简易容器,虽然粗糙,但能彻底破除黑盒感。
用典型场景反推组件作用
遇到问题时,顺着数据流倒查,比背文档更有效:
- 镜像拉不下来?先确认 dockerd 是否运行,再查 containerd 是否连得上 registry;
- 容器启动后立刻退出?用
docker logs看输出,本质是 shim 把 stdout/stderr 转给了 dockerd; - 多个容器端口冲突?说明 bridge 网络的 iptables 规则或端口映射没配对,这归 network manager 管;
- 磁盘空间暴涨?大概率是镜像层没清理,
docker system prune调用的是 dockerd 的垃圾回收逻辑。
不复杂但容易忽略:每次 docker info 输出里,其实已经列出了当前架构各组件的版本和状态,它是你手边最真实的架构图。











