mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-02-25 03:39:35 +00:00
157 lines
5.2 KiB
Go
157 lines
5.2 KiB
Go
## 14.1 基本架构
|
||
|
||
Docker 的架构设计简洁而高效,主要由客户端和服务端两部分组成。
|
||
|
||
### 核心架构图
|
||
|
||
Docker 采用了 **C/S (客户端/服务端)** 架构。Client 向 Daemon 发送请求,Daemon 负责构建、运行和分发容器。
|
||
|
||
```mermaid
|
||
graph LR
|
||
Client[客户端 (Docker CLI)] -- docker run --> Dockerd
|
||
Client -- docker pull --> Dockerd
|
||
|
||
subgraph "Docker Host"
|
||
Dockerd(dockerd<br>守护进程)
|
||
Containers(Containers<br>容器)
|
||
Images(Images<br>镜像)
|
||
|
||
Dockerd -- 管理 --> Containers
|
||
Dockerd -- 管理 --> Images
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
### 组件详解
|
||
|
||
Docker 的内部架构如同洋葱一样分层,每一层专注解决特定问题:
|
||
|
||
#### 1. Docker CLI(客户端)
|
||
|
||
用户与 Docker 交互的主要方式。它将用户命令(如 `docker run`)转换为 API 请求发送给 dockerd。
|
||
|
||
#### 2. Dockerd(守护进程)
|
||
|
||
Docker 的大脑。
|
||
- 监听 API 请求
|
||
- 管理 Docker 对象(镜像、容器、网络、卷)
|
||
- 编排下层组件完成工作
|
||
|
||
#### 3. Containerd(高级运行时)
|
||
|
||
行业标准的容器运行时(CNCF 毕业项目)。
|
||
- 管理容器的完整生命周期(启动、停止)
|
||
- 镜像拉取与存储
|
||
- **不包含** 复杂的与容器无关的功能(如构建、API)
|
||
- Kubernetes 也可以直接使用 containerd(跳过 Docker)
|
||
|
||
#### 4. Runc(低级运行时)
|
||
|
||
用于创建和运行容器的 CLI 工具。
|
||
- 直接与内核交互(Namespaces, Cgroups)
|
||
- 遵循 OCI (Open Container Initiative) 规范
|
||
- **主要职责**:根据配置启动一个容器,然后退出(将控制权交给容器进程)
|
||
|
||
#### 5. Shim
|
||
|
||
每个容器都有一个 shim 进程。
|
||
- **解耦**:允许 dockerd 重启而不影响容器运行
|
||
- **保持 IO**:维持容器的标准输入输出
|
||
- **状态汇报**:向 containerd 汇报容器退出状态
|
||
|
||
---
|
||
|
||
### 容器启动流程
|
||
|
||
当执行 `docker run -d nginx` 时,内部发生了什么?
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
User((用户))
|
||
|
||
subgraph DockerCLI [Docker CLI]
|
||
Cmd[docker run -d nginx]
|
||
end
|
||
|
||
subgraph DockerHost [Docker Host]
|
||
Dockerd[Dockerd]
|
||
Containerd[Containerd]
|
||
subgraph ContainerRuntime [Runtime]
|
||
Shim[Containerd-shim]
|
||
Runc[Runc]
|
||
Container[容器进程 (nginx)]
|
||
end
|
||
end
|
||
|
||
User --> Cmd
|
||
Cmd -- 1. REST API --> Dockerd
|
||
Dockerd -- 2. gRPC --> Containerd
|
||
Containerd -- 3. 准备镜像 & Bundle --> Containerd
|
||
Containerd -- 4. Fork --> Shim
|
||
Shim -- 5. Exec --> Runc
|
||
Runc -- 6. Create Namespaces/Cgroups --> Container
|
||
Runc -.-> |7. Exit| Runc
|
||
Shim -.-> |8. Monitor IO/Exit| Container
|
||
```
|
||
|
||
1. **CLI**发送请求给**Dockerd**
|
||
2. **Dockerd**解析请求,调用**Containerd**
|
||
3. **Containerd** 准备镜像,转换为 OCI Bundle
|
||
4. **Containerd**创建**Shim** 进程
|
||
5. **Shim**调用**Runc**
|
||
6. **Runc** 与系统内核交互,创建 Namespaces 和 Cgroups
|
||
7. **Runc** 启动 nginx 进程后退出
|
||
8. **Shim** 接管容器 IO 和生命周期监控
|
||
|
||
---
|
||
|
||
### Docker Engine v29+ 变化
|
||
|
||
从 Docker Engine v29 (2025/2026) 开始,架构进一步简化和标准化:
|
||
|
||
- **Containerd 镜像存储 (Image Store)**:默认启用。Docker 直接使用 Containerd 的镜像管理能力,不再维护自己的一套 graphdriver。
|
||
- **优势**:多平台镜像支持更好、镜像拉取更快(lazy pulling)、与 K8s 共享镜像。
|
||
|
||
---
|
||
|
||
### Docker Desktop 架构
|
||
|
||
在 macOS 和 Windows 上,因为内核差异,架构稍微复杂:
|
||
|
||
```
|
||
┌────────────── MacOS / Windows ──────────────┐
|
||
│ Docker CLI │
|
||
│ │ │
|
||
├──────┼──────────────────────────────────────┤
|
||
│ ▼ (Socket 映射) │
|
||
│ ┌────────── Linux VM (虚拟机) ───────────┐ │
|
||
│ │ │ │
|
||
│ │ Dockerd <--> Containerd <--> Runc │ │
|
||
│ │ │ │
|
||
│ └────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────┘
|
||
```
|
||
|
||
- 使用轻量级虚拟机(Apple Virtualization / WSL 2)运行 Linux 内核
|
||
- 文件挂载(Bind Mount)需要跨越 VM 边界(这也是文件 I/O 慢的原因)
|
||
- 网络端口需要从宿主机转发到 VM
|
||
|
||
---
|
||
|
||
### 总结
|
||
|
||
| 组件 | 角色 | 关键职责 |
|
||
|------|------|----------|
|
||
| **CLI** | 指挥官 | 发送指令,展示结果 |
|
||
| **Dockerd** | 大管家 | API 接口,整体调度 |
|
||
| **Containerd** | 经理 | 容器生命周期,镜像管理 |
|
||
| **Shim** | 监工 | 保持 IO,允许无守护进程重启 |
|
||
| **Runc** | 工人 | 真正干活(创建容器),干完就走 |
|
||
|
||
### 延伸阅读
|
||
|
||
- [命名空间](./14.2_namespace.md):Runc 如何隔离容器
|
||
- [控制组](./14.3_cgroups.md):Runc 如何限制资源
|
||
- [联合文件系统](./14.4_ufs.md):镜像如何存储
|