目錄
Docker 是什麼?
Docker 是一個容器化平台,讓你可以將應用程式及其依賴打包成獨立的容器。
核心概念
傳統方式:
應用程式直接安裝在作業系統上
→ 環境不一致
→ 依賴衝突
→ 難以遷移
Docker 方式:
應用程式 + 依賴 → 打包成容器
→ 環境一致
→ 隔離運行
→ 輕鬆遷移
為什麼要用 Docker?
1. 環境一致性
開發環境 = 測試環境 = 正式環境
「在我電腦上可以跑」的問題消失了!
2. 快速部署
建立 image → 在任何地方執行
幾秒鐘就能啟動應用程式
3. 資源隔離
每個容器獨立運行
不會互相影響
4. 版本控制
Image 像 Git 一樣有版本
可以輕鬆回溯
核心架構
整體架構圖
核心元件
1. Docker Client(客戶端)
你輸入的指令:
$ docker run nginx
→ Client 將指令透過 API 送到 Daemon
功能:
- 接收使用者指令
- 與 Docker Daemon 溝通
- 顯示執行結果
2. Docker Daemon(守護程序)
背景執行的服務 (dockerd)
負責:
- 管理 Images
- 管理 Containers
- 管理 Networks
- 管理 Volumes
功能:
- 監聽 Docker API 請求
- 管理 Docker 物件
- 與其他 Daemon 通訊
3. Docker Registry(註冊中心)
存放 Docker Images 的地方
公開的:Docker Hub (hub.docker.com)
私有的:自己架設的 Registry
功能:
- 儲存 Images
- 分享 Images
- 版本控制
4. 核心物件
| 物件 | 說明 | 詳細筆記 |
|---|---|---|
| Image | 唯讀模板,用來建立 Container | Docker Image Layer 詳解 |
| Container | Image 的執行實例 | Docker Container 容器詳解 |
| Volume | 資料持久化儲存 | Docker Volume 資料卷詳解 |
| Network | 容器間網路通訊 | Docker Network 網路詳解 |
運作原理
Namespace(命名空間)
Linux Namespace 提供隔離:
PID Namespace → 程序隔離
Network Namespace → 網路隔離
Mount Namespace → 檔案系統隔離
UTS Namespace → 主機名稱隔離
IPC Namespace → 程序間通訊隔離
User Namespace → 使用者隔離
結果:
每個 Container 看到的是獨立的環境
Cgroups(控制群組)
Linux Cgroups 提供資源限制:
CPU → 限制 CPU 使用
Memory → 限制記憶體使用
Disk I/O → 限制磁碟讀寫
Network → 限制網路頻寬
範例:
docker run -m 512m --cpus 1 myapp
Union File System(聯合檔案系統)
分層檔案系統:
Container Layer (讀寫層)
─────────────────────────
Image Layer 4 (唯讀)
Image Layer 3 (唯讀)
Image Layer 2 (唯讀)
Image Layer 1 (唯讀)
特點:
✅ 共享層次節省空間
✅ Copy-on-Write 機制
✅ 快速建立 Container
詳細說明請參考:Docker Image Layer 詳解
Copy-on-Write 機制
讀取檔案:
直接從 Image 層讀取
修改檔案:
1. 從 Image 層複製到 Container 層
2. 在 Container 層修改
3. 原 Image 層保持不變
優點:
✅ Image 保持不變
✅ 多個 Container 共享 Image
✅ 節省空間
實戰範例
範例 1:簡單 Web 應用
# 啟動 Nginx Web 伺服器
docker run -d \
--name web \
-p 8080:80 \
-v $(pwd)/html:/usr/share/nginx/html \
nginx
# 訪問:http://localhost:8080
範例 2:多容器應用
# 創建網路
docker network create app-net
# 啟動資料庫
docker run -d \
--name db \
--network app-net \
-e POSTGRES_PASSWORD=secret \
postgres
# 啟動應用
docker run -d \
--name app \
--network app-net \
-e DB_HOST=db \
-p 3000:3000 \
myapp
最佳實踐
1. 選擇適當的基礎 Image
# ✅ 好的做法:使用 alpine 版本
FROM node:18-alpine
# ❌ 不好的做法:使用完整版本
FROM node:18
2. 多階段建構
# ✅ 好的做法:分離建構和執行環境
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
FROM node:18-alpine
COPY /app/dist /app
CMD ["node", "/app/main.js"]
# ❌ 不好的做法:單一階段包含所有
FROM node:18
WORKDIR /app
COPY . .
RUN npm install && npm run build
CMD ["node", "dist/main.js"]
3. 使用具名 Volume
# ✅ 好的做法:使用具名 Volume
docker run -v mysql-data:/var/lib/mysql mysql
# ❌ 不好的做法:使用匿名 Volume
docker run -v /var/lib/mysql mysql
常見問題
Q1: Container 和 VM 有什麼區別?
A: Container 共享主機 OS 核心,更輕量;VM 需要完整的 Guest OS,資源佔用更多。Container 啟動速度快(秒級),VM 啟動慢(分鐘級)。
Q2: 為什麼需要 Volume?
A: Container 刪除後資料會消失。Volume 提供持久化儲存,資料獨立於 Container 生命週期,可以在多個 Container 間共享。
Q3: 如何選擇網路模式?
A:
- Bridge:預設模式,適合一般應用
- Host:需要最佳網路效能時使用
- Custom Network:生產環境推薦,支援 DNS 解析
Q4: Docker 適合什麼場景?
A:
- 微服務架構
- CI/CD 流程
- 開發環境統一
- 快速部署和擴展
應用場景
1. 微服務架構
單體應用 → 拆分成多個微服務
docker-compose.yml:
- API Gateway
- Auth Service
- User Service
- Order Service
- Payment Service
- Database
- Redis
- Message Queue
優點:
✅ 獨立部署
✅ 獨立擴展
✅ 技術棧自由
架構示意:
Internet
↓
┌────────────┐
│API Gateway │
└─────┬──────┘
│
┌─────────────┼─────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Auth │ │ User │ │ Order │
│ Service │ │ Service │ │ Service │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└─────────────┼─────────────┘
↓
┌──────────────────┐
│ Message Queue │
│ (Redis) │
└──────────────────┘
2. CI/CD 流程
開發 → 測試 → 部署
1. 程式碼提交 (Git)
↓
2. 建立 Docker Image (CI)
↓
3. 執行測試 (Container)
↓
4. 推送到 Registry
↓
5. 部署到環境 (CD)
優點:
✅ 環境一致
✅ 自動化
✅ 可重複
3. 開發環境
團隊開發環境統一:
docker-compose up -d
→ 啟動 Database
→ 啟動 Redis
→ 啟動 Message Queue
→ 啟動應用程式
優點:
✅ 新人快速上手
✅ 環境一致
✅ 不污染本機
4. 測試環境
隔離的測試環境:
docker run --rm myapp npm test
→ 執行測試
→ 自動刪除 Container
優點:
✅ 乾淨的環境
✅ 可重複
✅ 平行測試
5. Web 應用架構
┌─────────────┐
│ Nginx │ :80
│ (Proxy) │
└──────┬──────┘
│
┌───────────────┼───────────────┐
↓ ↓ ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│ App 1 │ │ App 2 │ │ App 3 │
│ Node.js │ │ Node.js │ │ Node.js │
└────┬────┘ └────┬────┘ └────┬────┘
└──────────────┼──────────────┘
↓
┌────────────────┐
│ PostgreSQL │
│ (Database) │
└────────┬───────┘
│
┌─────────┐
│ Volume │
│(持久化) │
└─────────┘
Container vs VM
架構差異
虛擬機(VM)架構:
┌─────────────────────────────────────┐
│ App A │ App B │ App C │
├─────────────┼─────────────┼─────────┤
│ Bin/Lib │ Bin/Lib │ Bin/Lib │
├─────────────┼─────────────┼─────────┤
│ Guest OS │ Guest OS │Guest OS │
├─────────────┴─────────────┴─────────┤
│ Hypervisor (VMware, etc) │
├─────────────────────────────────────┤
│ Host OS │
├─────────────────────────────────────┤
│ Hardware │
└─────────────────────────────────────┘
Docker(Container)架構:
┌─────────────────────────────────────┐
│ App A │ App B │ App C │
├─────────────┼─────────────┼─────────┤
│ Bin/Lib │ Bin/Lib │ Bin/Lib │
├─────────────┴─────────────┴─────────┤
│ Docker Engine │
├─────────────────────────────────────┤
│ Host OS │
├─────────────────────────────────────┤
│ Hardware │
└─────────────────────────────────────┘
比較表
| 項目 | Docker Container | 虛擬機 (VM) |
|---|---|---|
| 啟動速度 | 秒級 | 分鐘級 |
| 資源使用 | 輕量(MB) | 重量(GB) |
| 效能 | 接近原生 | 有損耗 |
| 隔離性 | 程序級別 | 硬體級別 |
| 作業系統 | 共享核心 | 獨立 OS |
| 移植性 | 非常好 | 較差 |
| 安全性 | 較弱 | 較強 |
使用場景
Docker(Container)適合:
✅ 微服務架構
✅ CI/CD 流程
✅ 快速部署
✅ 開發環境一致性
✅ 雲端原生應用
VM(虛擬機)適合:
✅ 需要完整 OS
✅ 不同核心的 OS(Windows on Linux)
✅ 強隔離需求
✅ 舊有應用(Legacy)
限制與注意事項
限制
❌ 不是虛擬機
→ 無法執行不同核心的 OS
❌ 狀態不持久
→ 需要使用 Volume
❌ 效能開銷
→ 雖小但仍存在
❌ 學習曲線
→ 需要理解概念
安全注意事項
⚠️ 不要使用 root
→ 使用 USER 指令
⚠️ 掃描漏洞
→ 定期更新 Image
⚠️ 限制資源
→ 防止單一 Container 吃光資源
⚠️ 敏感資訊
→ 不要寫在 Dockerfile
→ 使用 Secrets
⚠️ 網路隔離
→ 使用自訂網路
→ 最小權限原則
效能考量
✅ 選擇適當的基礎 Image
alpine > slim > 完整版
✅ 多階段建立
減少最終 Image 大小
✅ 適當的資源限制
防止影響其他服務
✅ Volume 效能
Named Volume > Bind Mount
✅ 網路模式選擇
Host > Bridge
總結
核心要點
- Docker 使用容器化技術提供輕量級、可移植的應用程式運行環境
- 核心架構:Client-Daemon-Registry 三層結構
- 四大核心物件:Image、Container、Volume、Network
- 使用 Namespace 和 Cgroups 實現隔離和資源限制
- 比 VM 更輕量、啟動更快、資源使用更少
快速參考
| 組件 | 作用 | 類比 |
|---|---|---|
| Image | 唯讀模板 | 程式檔案 |
| Container | 執行實例 | 執行中的程序 |
| Volume | 持久化儲存 | 硬碟 |
| Network | 網路通訊 | 網路連接 |
建立日期:2025-11-10 最後更新:2025-11-18