任務八:維運與安全性基礎¶
開始之前¶
任務目標
在這個任務中,你將學習:
- 使用資源限制控制容器的記憶體與 CPU 用量
- 設定容器重啟策略以提升服務可靠性
- 掌握日誌管理與查看技巧
- 維護 Docker 環境整潔:清理未使用的資源
- 診斷與處理異常狀態的容器
- 建立安全性基礎觀念:非 root 執行、可信任映像檔、弱點掃描
資源限制:控制容器的資源使用¶
為何需要資源限制¶
在預設情況下,Docker 容器可以使用主機上所有可用的記憶體與 CPU。這可能導致:
- 單一容器耗盡資源:失控的容器可能佔用所有記憶體,導致主機或其他容器無法運作
- 系統不穩定:記憶體不足可能觸發 OOM Killer,強制終止程式
- 效能下降:沒有 CPU 限制的容器可能影響其他服務的效能
透過設定資源限制,你可以:
- 防止單一容器影響整個系統
- 確保重要服務獲得足夠資源
- 在有限資源下執行更多容器
限制記憶體用量¶
使用 --memory 參數限制容器可使用的記憶體:
# 限制記憶體為 512MB
docker run -d --name nginx-limited --memory 512m nginx:alpine
# 限制記憶體為 1GB
docker run -d --name nginx-1g --memory 1g nginx:alpine
常用單位:
m或M:MB(百萬位元組)g或G:GB(十億位元組)
當容器嘗試使用超過限制的記憶體時,會被 OOM Killer 終止。
限制 CPU 用量¶
使用 --cpus 參數限制容器可使用的 CPU 核心數:
# 限制為 0.5 個 CPU 核心(50% 的單核效能)
docker run -d --name nginx-half-cpu --cpus 0.5 nginx:alpine
# 限制為 2 個 CPU 核心
docker run -d --name nginx-2cpu --cpus 2 nginx:alpine
說明:
--cpus 1:容器最多使用 1 個 CPU 核心的完整效能--cpus 0.5:容器最多使用 0.5 個 CPU 核心的效能--cpus 2:容器最多使用 2 個 CPU 核心的效能
與記憶體限制不同,CPU 限制不會終止容器,只會限制其運算速度。
查看容器資源使用狀況¶
使用 docker stats 即時監控容器的資源使用情況:
輸出範例:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O
a1b2c3d4e5f6 nginx-limited 0.01% 5.5MiB / 512MiB 1.07% 1.2kB / 0B
欄位說明:
CPU %:CPU 使用百分比MEM USAGE / LIMIT:記憶體使用量與限制MEM %:記憶體使用百分比NET I/O:網路輸入/輸出流量
按 Ctrl+C 退出即時監控。
容器重啟策略:提升服務可靠性¶
重啟策略對照表¶
Docker 提供四種重啟策略,用於控制容器在退出後是否自動重啟:
| 策略 | 說明 | daemon 重啟後 |
|---|---|---|
no |
不自動重啟(預設) | 不啟動 |
on-failure |
僅在非正常退出時重啟 | 不啟動 |
always |
無論原因都重啟 | 自動啟動 |
unless-stopped |
與 always 類似,但手動停止的不會啟動 |
如果之前在執行則啟動 |
no:預設策略¶
說明:
- 容器停止後不會自動重啟
- 這是預設行為
- 適合用於一次性任務或開發環境
on-failure:非正常退出時重啟¶
# 非正常退出時重啟
docker run -d --name app-on-failure --restart on-failure nginx:alpine
# 最多重試 3 次
docker run -d --name app-retry-3 --restart on-failure:3 nginx:alpine
說明:
- 只在容器以非 0 的退出碼結束時重啟
- 可設定最大重試次數(如
on-failure:3) - 適合用於可能暫時失敗的服務
適用情境:
- 資料處理任務:可能因暫時性錯誤失敗,重試後可能成功
- 連接外部服務:初次啟動時外部服務可能尚未就緒
always:始終重啟¶
說明:
- 無論容器以何種原因退出,都會自動重啟
- Docker daemon 重啟後,容器也會自動啟動
- 容器會無限次重試
適用情境:
- 生產環境的核心服務(Web 應用、API 伺服器)
- 需要持續運行的背景服務
unless-stopped:除非手動停止¶
說明:
- 與
always類似,但有一個關鍵差異:- 如果你手動執行
docker stop停止容器,Docker daemon 重啟後不會自動啟動該容器 - 如果容器是自己退出的(非手動停止),daemon 重啟後會自動啟動
- 如果你手動執行
- 這讓你能明確控制哪些容器不該啟動
適用情境:
- 大多數生產服務(比
always更靈活) - 需要臨時停止某些服務進行維護的場景
適用情境總結¶
- 開發環境:使用
no或on-failure,避免容器在背景不斷重啟 - 測試環境:使用
on-failure,失敗時自動重試 - 生產環境:優先使用
unless-stopped或always,確保服務持續運行
日誌管理:追蹤容器輸出¶
預設日誌機制¶
Docker 使用 json-file 作為預設的 log driver。容器的標準輸出(stdout)與標準錯誤(stderr)會被儲存為 JSON 格式的日誌檔案,通常位於:
你可以透過 docker logs 指令查看這些日誌,無需直接存取檔案。
基本用法¶
持續追蹤日誌¶
使用 -f 參數可即時追蹤新產生的日誌,類似 tail -f:
按 Ctrl+C 停止追蹤。
適用情境:
- 除錯應用程式
- 監控服務運行狀態
- 查看即時的請求或錯誤訊息
限制顯示行數¶
使用 --tail 參數只顯示最後 N 行日誌:
時間過濾¶
使用 --since 參數過濾指定時間之後的日誌:
# 顯示最近 10 分鐘的日誌
docker logs --since 10m my-app
# 顯示最近 1 小時的日誌
docker logs --since 1h my-app
# 顯示某個時間點之後的日誌
docker logs --since "2026-02-03T10:00:00" my-app
常用時間單位:
s:秒m:分鐘h:小時
限制日誌檔案大小¶
在生產環境中,日誌可能快速累積並佔用大量磁碟空間。你可以在啟動容器時設定日誌大小限制:
參數說明:
--log-opt max-size=10m:單一日誌檔案最大 10MB--log-opt max-file=3:最多保留 3 個日誌檔案
當日誌檔案達到 10MB 時,Docker 會建立新的日誌檔案。當檔案數量超過 3 個時,最舊的檔案會被刪除。
系統清理:維護 Docker 環境¶
隨著使用時間增長,Docker 會累積許多未使用的資源:已停止的容器、懸空的映像檔、未使用的 volume 與網路。定期清理這些資源可以:
- 釋放磁碟空間
- 提升系統效能
- 避免資源列表過於雜亂
清理已停止的容器¶
這個指令會移除所有狀態為 exited 的容器。
輸出範例:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
a1b2c3d4e5f6
g7h8i9j0k1l2
Total reclaimed space: 245MB
清理未使用的映像檔¶
懸空映像檔(Dangling Images):
- 指沒有標籤(tag)的映像檔
- 通常是重新建立映像檔時產生的舊版本
- 在
docker images中顯示為<none>:<none>
-a 參數:
- 移除所有未被任何容器(包含已停止的容器)使用的映像檔
- 使用時需謹慎,確保不會刪除之後還需要的映像檔
清理未使用的 Volume¶
這個指令會移除所有未被任何容器(包含已停止的容器)掛載的 volume。
注意
Volume 通常包含重要的應用資料(如資料庫檔案)。執行 volume prune 前請確認沒有需要保留的資料。
清理未使用的網路¶
這個指令會移除所有未被任何容器使用的自訂網路(預設網路如 bridge、host、none 不會被刪除)。
一次清理多種資源¶
# 清理容器、映像檔、網路
docker system prune
# 清理容器、映像檔、網路、volume
docker system prune --volumes
# 清理所有未使用的映像檔(不只是懸空的)
docker system prune -a
常用選項:
--volumes:同時清理未使用的 volume-a或--all:清理所有未使用的映像檔,而非只有懸空的-f或--force:跳過確認提示,直接執行清理
輸出範例:
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all dangling images
- all dangling build cache
Are you sure you want to continue? [y/N]
確認機制與強制執行¶
預設情況下,所有 prune 指令都會要求確認。如果你確定要清理,可以使用 -f 跳過確認:
謹慎使用 -f
使用 -f 時請確保你清楚知道哪些資源會被刪除,避免誤刪重要資料。
容器異常處理:診斷與修復¶
常見的容器狀態¶
Docker 容器可能處於以下幾種狀態:
| 狀態 | 說明 |
|---|---|
created |
容器已建立但尚未啟動 |
running |
容器正在執行 |
paused |
容器已暫停(程式被凍結) |
exited |
容器已停止 |
dead |
容器處於無法操作的狀態 |
使用 docker ps -a 可以查看所有容器的狀態:
輸出範例:
CONTAINER ID IMAGE STATUS NAMES
a1b2c3d4e5f6 nginx:alpine Up 2 hours web
g7h8i9j0k1l2 postgres:18 Exited (1) 5 minutes ago db
m3n4o5p6q7r8 redis:alpine Dead cache
診斷 exited 狀態的容器¶
當容器處於 exited 狀態時,你需要查看退出碼(exit code)來判斷原因。
使用 docker inspect 查看容器的詳細資訊:
或查看完整的退出資訊:
輸出範例:
{
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 1,
"Error": "",
"StartedAt": "2026-02-03T10:30:00.123456789Z",
"FinishedAt": "2026-02-03T10:35:00.987654321Z"
}
常見退出碼的含義¶
| 退出碼 | 含義 | 可能原因 |
|---|---|---|
0 |
正常退出 | 程式執行完成或被正常終止 |
1 |
一般錯誤 | 應用程式內部錯誤、設定錯誤 |
137 |
被 SIGKILL 終止 | 記憶體不足(OOM)或被強制終止 |
139 |
Segmentation Fault | 程式崩潰(segfault) |
143 |
被 SIGTERM 終止 | 收到終止信號(通常是 docker stop) |
除錯步驟:
- 查看退出碼:
docker inspect <container> --format='{{.State.ExitCode}}' - 查看容器日誌:
docker logs <container> - 根據退出碼與日誌判斷問題
- 修正問題後重新啟動容器
處理 dead 狀態的容器¶
dead 狀態通常表示容器無法被正常移除。這可能是因為:
- Docker daemon 異常
- 檔案系統問題
- 資源鎖定
處理方式:
# 嘗試強制移除
docker rm -f <container>
# 如果仍無法移除,重啟 Docker daemon
# Linux/macOS
sudo systemctl restart docker
# Docker Desktop
# 從系統托盤重啟 Docker Desktop
使用日誌除錯¶
當容器無法正常運作時,日誌是最重要的除錯資訊來源:
# 查看完整日誌
docker logs my-app
# 查看最後 50 行日誌
docker logs --tail 50 my-app
# 持續追蹤日誌
docker logs -f my-app
常見問題模式:
- 應用程式無法啟動:檢查日誌中的錯誤訊息(如 missing environment variable)
- 容器立即退出:檢查日誌與退出碼,可能是啟動指令錯誤
- 容器重複重啟:檢查日誌與重啟策略,可能是應用程式無法連接依賴服務
安全性基礎¶
避免以 root 執行容器¶
風險說明¶
預設情況下,容器內的程式以 root 使用者身份執行。雖然容器提供了一定程度的隔離,但如果發生容器逃逸(container escape),攻擊者可能以 root 權限影響主機系統。
最佳實踐:除非必要,否則應以非 root 使用者執行容器。
使用 --user 參數¶
在啟動容器時指定執行使用者:
# 以 UID 1000 的使用者執行
docker run -d --name app --user 1000 nginx:alpine
# 以特定使用者與群組執行
docker run -d --name app --user 1000:1000 nginx:alpine
在 Dockerfile 中設定 USER¶
更好的做法是在 Dockerfile 中指定預設執行使用者:
FROM node:20-alpine
# 建立非 root 使用者
RUN addgroup -g 1001 appgroup && \
adduser -D -u 1001 -G appgroup appuser
# 設定工作目錄
WORKDIR /app
# 複製應用程式檔案
COPY package*.json ./
RUN npm install
COPY . .
# 切換到非 root 使用者
USER appuser
# 啟動應用程式
CMD ["node", "index.js"]
這樣建立的映像檔,在執行時預設就會以非 root 使用者身份執行。
使用可信任的映像檔¶
優先使用 Docker Official Images¶
Docker Official Images 是由 Docker 官方或軟體供應商維護的映像檔,經過安全審核與定期更新。
識別方式:
- 映像檔名稱簡短,沒有使用者名稱前綴(如
nginx、postgres、python) - 在 Docker Hub 上會顯示 DOCKER OFFICIAL IMAGE 標籤
優點:
- 定期更新與安全修補
- 遵循最佳實踐
- 社群支援充足
認識 Verified Publisher¶
Verified Publisher 標籤表示該映像檔由經過 Docker 驗證的發行商提供。這些發行商通常是知名軟體公司(如 Microsoft、Red Hat)。
雖然不如官方映像檔,但 Verified Publisher 的映像檔仍值得信任。
避免使用 latest 標籤¶
latest 標籤指向映像檔的最新版本,但這會帶來以下問題:
- 不可預測性:
latest可能隨時改變,導致應用程式行為不一致 - 難以復現問題:無法確定當時使用的是哪個版本
- 潛在的破壞性更新:新版本可能引入不相容的變更
最佳實踐:使用具體的版本標籤。
# ❌ 避免
docker pull nginx:latest
# ✅ 建議
docker pull nginx:1.25-alpine
docker pull postgres:18.1
docker pull python:3.12.1-slim
映像檔弱點掃描:Docker Scout¶
什麼是 Docker Scout¶
Docker Scout 是 Docker 官方提供的弱點掃描工具,可以分析映像檔中的已知安全弱點(CVE,Common Vulnerabilities and Exposures)。
Docker Scout 整合在 Docker CLI 中,無需額外安裝。
快速查看弱點摘要¶
使用 docker scout quickview 快速查看映像檔的弱點摘要:
輸出範例:
✓ Provenance: inferred
✓ SBOM: detected
Target: nginx:1.25-alpine (linux/arm64)
Critical: 0
High: 1
Medium: 3
Low: 8
Unspecified: 0
這個指令會顯示映像檔中不同嚴重程度的弱點數量。
查看詳細的 CVE 列表¶
使用 docker scout cves 查看詳細的弱點列表:
輸出範例(擷取):
✓ Provenance: inferred
✓ SBOM: detected
Target: nginx:1.25-alpine (linux/arm64)
## Critical Vulnerabilities
No critical vulnerabilities found
## High Vulnerabilities
1 high vulnerabilities found in 1 package
CVE-2024-1234 HIGH
Package: libssl3
Current version: 3.1.0-r1
Fixed in: 3.1.1-r0
Link: https://scout.docker.com/v/CVE-2024-1234
弱點嚴重程度分級¶
Docker Scout 使用 CVSS(Common Vulnerability Scoring System)標準評估弱點嚴重程度:
| 等級 | 說明 | 建議處理 |
|---|---|---|
| Critical | 極嚴重弱點,可能導致完全入侵 | 立即修補或更換映像檔 |
| High | 高風險弱點,可能嚴重影響安全 | 盡快修補 |
| Medium | 中等風險弱點 | 視情況修補 |
| Low | 低風險弱點 | 可後續處理 |
處理建議:
- 優先修補 Critical 與 High 等級的弱點
- 檢查是否有更新的映像檔版本可用
- 如果映像檔無法更新,評估弱點的實際影響
- 在生產環境使用映像檔前,務必掃描弱點
工作流程範例:
# 1. 掃描映像檔
docker scout quickview myapp:latest
# 2. 如果發現高風險弱點,查看詳細資訊
docker scout cves myapp:latest
# 3. 根據建議更新基礎映像檔或套件
# 4. 重新建立映像檔
docker build -t myapp:latest .
# 5. 再次掃描確認問題已修復
docker scout quickview myapp:latest
任務結束¶
完成!
恭喜你完成了這個任務!現在你已經學會:
- 使用資源限制控制容器的記憶體與 CPU 用量
- 設定容器重啟策略以提升服務可靠性
- 掌握日誌管理與查看技巧
- 維護 Docker 環境整潔:清理未使用的資源
- 診斷與處理異常狀態的容器
- 建立安全性基礎觀念:非 root 執行、可信任映像檔、弱點掃描
這些知識與技能是邁向生產環境的重要基礎,能幫助你建立更穩定、安全、易於維護的容器化應用。