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 開始,安全性思維就應該隨行。