Docker 安全性最佳實踐
隨意從網路上抓取映像檔並執行,就像隨便撿起地上的 USB 隨身碟插進電腦一樣危險。容器雖然提供了隔離環境,但並非「不可攻破」。為了讓你的服務在生產環境中穩健運行,必須遵循「深度防禦」原則。
最小權限原則:非特權運行
永遠不要使用 Root 使用者
預設情況下,Docker 內的程式是以 root 身份執行的。如果駭客攻破了容器內的程式,他極有能透過提權漏洞直接獲取宿主機 (Host) 的控制權。
在 Dockerfile 中務必建立並切換至非特權使用者:
# 建立使用者
RUN adduser -D appuser
# 切換使用者
USER appuser
進階:Rootless 模式
Docker 支援 Rootless 模式,讓 Docker Daemon 本身也運行在非 root 使用者下。這徹底杜絕了容器逃逸後獲取宿主機 root 權限的可能性。
供應鏈安全:映像檔掃描與簽章
映像檔安全性掃描 (Docker Scout)
使用 Docker Scout 自動識別映像檔中的已知漏洞 (CVE):
docker scout quickview [IMAGE_NAME]
最佳實踐:
- 使用官方認證 (Official) 的映像檔。
- 優先選用
-alpine或-slim版本,減少受攻擊面。
Docker Content Trust (DCT)
為了防止下載到遭竄改的映像檔,可開啟 內容信任機制 (DCT)。開啟後,Docker 只會拉取經過簽署的映像檔。
# 開啟簽章檢驗環境變數
export DOCKER_CONTENT_TRUST=1
# 此時若下載未經簽章的映像檔將會失敗
docker pull my-untrusted-image
權限管控:Capabilities 與系統調用
Linux Capabilities 管理
Linux 將 root 權限拆分為多個細粒度的 Capabilities。最安全的做法是先移除所有權限,再根據需求逐一補回:
# 移除所有權限,僅補回基本的網路埠號綁定權限
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx
防止權限提升
透過 --security-opt 限制容器進程獲取新權限(如透過 setuid):
# 禁止獲取新權限
docker run --security-opt=no-new-privileges:true my-app
機密資訊管理 (Secrets)
絕對不要將資料庫密碼或 API Key 寫死在 Dockerfile 或環境變數中,因為 docker inspect 能直接看見環境變數。
使用 Docker Secrets
在 Swarm 模式或 Compose 中使用:
services:
db:
image: postgres
secrets:
- db_password
secrets:
db_password:
external: true
密碼會掛載到 /run/secrets/db_password,這是一個純記憶體的唯讀檔案系統,安全性極高。
運行時加固
唯讀檔案系統
如果應用程式不需寫入檔案(如靜態網站),強烈建議開啟唯讀模式。
docker run -d --read-only nginx
網路安全隔離
不要依賴預設的 bridge 網路。請建立 自訂網路 並依需求關閉容器間互通 (ICC):
# 建立禁止容器間互通的網絡
docker network create --opt com.docker.network.bridge.enable_icc=false my-safe-net
資源限制 (DoS 防禦)
設定 CPU 與記憶體上限。這能防止惡意程式耗盡主機資源導致服務中斷。
安全檢查清單 (TL;DR)
-
Dockerfile是否使用了USER指令? - 是否使用了輕量級基礎映像檔 (Alpine/Slim)?
- 敏感資訊是否已使用
Secret管理? - 是否已設定 CPU 與記憶體限額?
- 映像檔是否經過
Docker Scout掃描? - 是否已根據最小權限原則
cap-drop不需要的權限?
安全不只是維運團隊的事,從撰寫第一行 Dockerfile 開始,安全性思維就應該隨行。