CMD 與 ENTRYPOINT 的差別與 exec form 的 SIGTERM 陷阱
兩個都是「容器啟動時執行什麼」,差別在能不能被
docker run後面的參數覆寫。
差別
| CMD | ENTRYPOINT | |
|---|---|---|
| 遇到 run 的參數 | 被整個取代 | 不會被取代,參數接在後面 |
| 定位 | 「預設」指令,可換 | 「固定」的執行檔 |
CMD ["node", "server.js"]
docker run my-app → node server.js
docker run my-app ls -la → ls -la(CMD 被整個換掉)
ENTRYPOINT ["node"]
docker run my-app --version → node --version(接在後面)最實用的是組合技——ENTRYPOINT 定固定執行檔,CMD 提供可覆寫的預設參數:
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run my-app → node server.js
# docker run my-app worker.js → node worker.js⚠️ 一律用 JSON 陣列(exec form)
寫成字串的 shell form CMD node server.js 會多包一層 /bin/sh -c,訊號被 sh 吃掉沒傳給你的程式,於是:
docker stop時程式收不到 SIGTERM、不會優雅關閉- Docker 等 10 秒沒反應才 SIGKILL 硬砍(這就是「
docker stop要等 10 秒」的元兇)
解法是 exec form CMD ["node","server.js"],並在程式裡監聽 SIGTERM 做優雅關閉 → 容器設計原則:單一職責、無狀態、設定走環境變數。