Docker 系统架构
本章将深入讲解 Docker 的系统架构设计,帮助你理解 Docker 各组件之间的协作关系和底层技术原理。
Docker 整体架构
Docker 采用经典的客户端-服务器(C/S)架构,由三个核心部分组成:
┌──────────────────────────────────────────────────────────────────┐
│ Docker 架构全景 │
│ │
│ ┌──────────────┐ ┌──────────────────────────────────┐ │
│ │ Docker CLI │ │ Docker Daemon │ │
│ │ │ REST │ ┌────────┐ ┌────────┐ │ │
│ │ docker build │ API │ │ Images │ │Containers│ │ │
│ │ docker pull │◄───────►│ └────────┘ └────────┘ │ │
│ │ docker run │ │ ┌────────┐ ┌────────┐ │ │
│ │ docker ps │ │ │Networks│ │ Volumes│ │ │
│ └──────────────┘ │ └────────┘ └────────┘ │ │
│ └──────────────┬───────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────┐ │
│ │ Docker Registry │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │Docker Hub│ │ 私有仓库 │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘核心组件详解
1. Docker Client(客户端)
Docker Client 是用户与 Docker 交互的主要方式,通过命令行工具 docker 发送请求。
bash
# 客户端命令示例
docker run nginx # 运行容器
docker build -t myapp . # 构建镜像
docker pull ubuntu # 拉取镜像
docker ps # 查看容器客户端通过 REST API 与 Docker Daemon 通信,支持以下连接方式:
| 连接方式 | 说明 | 示例 |
|---|---|---|
| Unix Socket | 本地通信(默认) | /var/run/docker.sock |
| TCP | 远程通信 | tcp://192.168.1.100:2376 |
| SSH | 安全远程通信 | ssh://user@host |
2. Docker Daemon(守护进程)
Docker Daemon(dockerd)是 Docker 的核心服务进程,负责:
- 监听 Docker API 请求
- 管理 Docker 对象(镜像、容器、网络、数据卷)
- 与其他 Docker Daemon 通信(集群模式)
bash
# 查看 Docker Daemon 状态
sudo systemctl status docker
# Docker Daemon 配置文件
cat /etc/docker/daemon.json3. Docker Registry(镜像仓库)
Registry 是存储和分发 Docker 镜像的服务:
- Docker Hub:官方公共仓库,包含大量官方和社区镜像
- 私有仓库:企业内部搭建,如 Harbor、Nexus
- 云服务商仓库:阿里云 ACR、腾讯云 TCR、AWS ECR 等
Docker 底层技术
Docker 利用 Linux 内核的多项技术实现容器隔离和资源管理:
Namespace(命名空间)
Namespace 提供了容器的隔离能力,让每个容器拥有独立的系统视图:
| Namespace | 隔离内容 | 说明 |
|---|---|---|
| PID | 进程 ID | 容器内进程与宿主机进程隔离 |
| NET | 网络 | 独立的网络栈、IP 地址、端口 |
| MNT | 文件系统挂载 | 独立的文件系统视图 |
| UTS | 主机名和域名 | 容器拥有独立的主机名 |
| IPC | 进程间通信 | 独立的信号量、消息队列 |
| USER | 用户和用户组 | 容器内外用户映射 |
Cgroups(控制组)
Cgroups 负责限制和监控容器的资源使用:
bash
# 限制容器使用最多 512MB 内存和 1 个 CPU
docker run -m 512m --cpus 1 nginx
# 查看容器资源使用情况
docker stats| 资源类型 | 控制能力 |
|---|---|
| CPU | 限制 CPU 使用时间和核心数 |
| 内存 | 限制内存使用上限 |
| 磁盘 I/O | 限制读写速率 |
| 网络 | 限制网络带宽 |
Union File System(联合文件系统)
Docker 镜像采用分层存储架构,使用联合文件系统(如 OverlayFS)实现:
┌─────────────────────────┐
│ 可写层(容器层) │ ← 容器运行时的修改
├─────────────────────────┤
│ 应用层 │ ← COPY/ADD 指令
├─────────────────────────┤
│ 依赖层 │ ← RUN apt-get install
├─────────────────────────┤
│ 基础镜像层 │ ← FROM ubuntu:22.04
└─────────────────────────┘分层存储的优势:
- 共享基础层:多个镜像可以共享相同的基础层,节省磁盘空间
- 快速构建:只需重建变化的层,加速镜像构建
- 高效分发:只需传输差异层,减少网络传输
Docker 运行时架构
containerd 与 runc
Docker 的容器运行时经历了架构演进:
Docker CLI → Docker Daemon → containerd → runc → 容器进程| 组件 | 职责 |
|---|---|
| Docker Daemon | 接收 API 请求,管理镜像和高级功能 |
| containerd | 容器生命周期管理(创建、启动、停止) |
| runc | OCI 标准容器运行时,负责实际创建容器 |
OCI 标准
OCI(Open Container Initiative)定义了容器的开放标准:
- 运行时规范:定义容器如何运行
- 镜像规范:定义镜像格式
- 分发规范:定义镜像如何分发
Docker 网络架构
Docker 提供多种网络驱动,满足不同场景需求:
bash
# 查看 Docker 网络
docker network ls| 网络模式 | 说明 | 适用场景 |
|---|---|---|
| bridge | 默认模式,容器通过虚拟网桥通信 | 单机容器通信 |
| host | 容器直接使用宿主机网络 | 高性能网络需求 |
| none | 无网络连接 | 安全隔离场景 |
| overlay | 跨主机容器通信 | Docker Swarm 集群 |
| macvlan | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
Docker 存储架构
Docker 提供多种数据持久化方案:
┌─────────────────────────────────────────────┐
│ Docker 容器 │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Volume │ │ Bind │ │ tmpfs │ │
│ │ Mount │ │ Mount │ │ Mount │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
└───────┼─────────────┼───────────┼───────────┘
│ │ │
▼ ▼ ▼
Docker 管理 宿主机目录 内存文件系统
的数据卷| 存储类型 | 管理方式 | 持久化 | 适用场景 |
|---|---|---|---|
| Volume | Docker 管理 | 是 | 数据库、应用数据 |
| Bind Mount | 用户指定路径 | 是 | 开发环境、配置文件 |
| tmpfs | 内存存储 | 否 | 临时数据、敏感信息 |
本章小结
Docker 的系统架构设计精巧,通过客户端-服务器模式提供简洁的用户接口,利用 Linux 内核的 Namespace、Cgroups 和联合文件系统实现轻量级容器隔离。理解这些底层原理,有助于你在实际使用中更好地排查问题和优化性能。
关键要点:
- Docker 采用 C/S 架构,Client 通过 REST API 与 Daemon 通信
- Namespace 提供隔离,Cgroups 提供资源限制
- 联合文件系统实现镜像分层存储,提高效率
- containerd 和 runc 负责容器的实际运行
- Docker 提供多种网络和存储方案适配不同场景