容器設計原則:單一職責、無狀態、設定走環境變數
主張:容器化的難點不在指令,在設計。這五條決定了你的容器能不能被隨便砍掉重開、能不能一份 image 打天下。
五條
- 一個容器一個職責 — 不要把 nginx + app + mysql 塞進同一個容器。要三個服務就三個容器。
- 無狀態、可拋棄 — 任何需要留下來的東西都放 volume 或外部服務,「隨時可以被砍掉重開」是設計目標(見 容器可拋棄,資料要靠 Volume 留在容器外)。
- 設定從環境變數進來 — 同一份 image 應該能靠環境變數跑在 dev / staging / prod,不要為每個環境 build 不同 image。
- log 印到 stdout/stderr — 不要寫進容器裡的檔案,Docker 和 K8s 的日誌系統都是收 stdout 的。
- 處理 SIGTERM — 用 exec form 的 CMD 並在應用程式裡監聽 SIGTERM 做優雅關閉,不然
docker stop會硬砍你的連線(見 CMD 與 ENTRYPOINT 的差別與 exec form 的 SIGTERM 陷阱)。
安全清單
- 不要用 root 跑容器 — Dockerfile 加
USER node;容器逃逸時 root 的殺傷力完全不同 - 密碼絕對不要寫進 Dockerfile —
ENV、ARG都會留在 image metadata,docker history就看得到。用docker run -e、secret 服務或 BuildKit secret mount - 寫好
.dockerignore— 否則.env、.git、金鑰會被烤進 image,build 也會變慢變肥 - 釘住基底版本、掃漏洞(
docker scout cves/ trivy)、最小化 image、不必要就不開 port
正式環境另外設 --memory / --cpus 上限,防止單一容器拖垮主機。