12.1 基本架構
Docker 的架構設計簡潔而高效,主要由用戶端和伺服器端兩部分組成。
12.1.1 核心架構圖
Docker 採用了 C/S (用戶端/伺服器端) 架構。Client 向 Daemon 傳送請求,Daemon 負責建立、執行和分發容器。
graph LR
C1["用戶端"] -->|docker run| D["dockerd
守護程序"] C1 -->|docker pull| D D -->|管理| C2["Containers
容器"] D -->|管理| C3["Images
映象"]
守護程序"] C1 -->|docker pull| D D -->|管理| C2["Containers
容器"] D -->|管理| C3["Images
映象"]
12.1.2 元件詳解
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 彙報容器退出狀態
12.1.3 容器啟動流程
當執行 docker run -d nginx 時,內部發生了什麼?
flowchart TD
U["使用者"]
K["docker run -d nginx"]
D["Dockerd"]
C["Containerd"]
B["OCI Bundle"]
S["Containerd-shim"]
R["Runc"]
P["容器程序
nginx"] E["退出"] U -->|1. REST API| D D -->|2. gRPC| C C -->|3. 準備映象和 Bundle| B C -->|4. 啟動 Shim| S S -->|5. 執行| R R -->|6. 建立 Namespaces 和 Cgroups| P R -->|7. 程序退出| E S -->|8. 監控 IO 和退出| P
nginx"] E["退出"] U -->|1. REST API| D D -->|2. gRPC| C C -->|3. 準備映象和 Bundle| B C -->|4. 啟動 Shim| S S -->|5. 執行| R R -->|6. 建立 Namespaces 和 Cgroups| P R -->|7. 程序退出| E S -->|8. 監控 IO 和退出| P
- CLI 傳送請求給 Dockerd
- Dockerd 解析請求,呼叫 Containerd
- Containerd 準備映象,轉換為 OCI Bundle
- Containerd 建立 Shim 程序
- Shim 呼叫 Runc
- Runc 與系統核心互動,建立 Namespaces 和 Cgroups
- Runc 啟動 nginx 程序後退出
- Shim 接管容器 IO 和生命週期監控
12.1.4 Docker Engine v29.x 變化
從 Docker Engine v29.x 開始,架構進一步簡化和標準化:
- Containerd 映象儲存 (Image Store):在 v29.x 的新安裝場景中預設啟用。Docker 直接使用 Containerd 的映象管理能力,不再維護自己的一套 graphdriver。
- 優勢:多平臺映象支援更好,可儲存 SBOM/Provenance 等 attestations,並可使用 containerd snapshotters 的 lazy pulling 等能力。
- 實驗性 nftables 支援:隨著主流 Linux 發行版逐步棄用 iptables,Docker v29.x 引入了實驗性 nftables 後端。啟用方式為
dockerd --firewall-backend=nftables,可直接建立 nftables 規則而無需依賴 iptables-nft 轉換層。生產環境請謹慎使用。
12.1.5 Docker Desktop 架構
在 macOS 和 Windows 上,因為核心差異,架構稍微複雜:
flowchart TD
subgraph HostOS ["MacOS / Windows"]
CLI["Docker CLI"]
subgraph LinuxVM ["Linux VM (虛擬機)"]
Engine["Dockerd <--> Containerd <--> Runc"]
end
CLI -- "(Socket 對映)" --> Engine
end
- 使用輕量級虛擬機 (Apple Virtualization / WSL 2) 執行 Linux 核心
- 檔案掛載 (Bind Mount) 需要跨越 VM 邊界 (這也是檔案 I/O 慢的原因)
- 網路連接埠需要從宿主機轉發到 VM
12.1.6 總結
| 元件 | 角色 | 關鍵職責 |
|---|---|---|
| CLI | 指揮官 | 傳送指令,展示結果 |
| Dockerd | 大管家 | API 介面,整體排程 |
| Containerd | 經理 | 容器生命週期,映象管理 |
| Shim | 監工 | 保持 IO,允許無守護程序重啟 |
| Runc | 工人 | 真正幹活 (建立容器),幹完就走 |