建議使用 JSON 格式參數 (JSONArgsRecommended)
目錄
輸出
JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals
說明
ENTRYPOINT
和 CMD
指令都支援兩種不同的參數語法
- Shell 格式:
CMD my-cmd start
- Exec 格式:
CMD ["my-cmd", "start"]
當您使用 Shell 格式時,可執行檔會以 Shell 的子程序執行,這不會傳遞訊號。這表示在容器中執行的程式無法偵測到 SIGTERM
和 SIGKILL
等作業系統訊號,也無法正確回應它們。
範例
❌ 不良:ENTRYPOINT
指令未收到作業系統訊號。
FROM alpine
ENTRYPOINT my-program start
# entrypoint becomes: /bin/sh -c my-program start
為了確保可執行檔可以接收作業系統訊號,請使用 Exec 格式的 CMD
和 ENTRYPOINT
,這可讓您將可執行檔作為容器中的主要程序(PID 1
)執行,避免 Shell 父程序。
✅ 良好:ENTRYPOINT
收到作業系統訊號。
FROM alpine
ENTRYPOINT ["my-program", "start"]
# entrypoint becomes: my-program start
請注意,將程式作為 PID 1 執行表示該程式現在具有與 Linux 中 PID 1 相關的特殊職責和行為,例如回收子程序。
解決方案
在某些情況下,您可能仍然希望在 Shell 下執行容器。使用 Exec 格式時,Shell 功能(例如變數展開、管道(|
)和命令鏈接(&&
、||
、;
))將無法使用。要使用這些功能,您需要使用 Shell 格式。
以下是一些您可以實現的方法。請注意,這仍然表示可執行檔會以 Shell 的子程序執行。
建立包裝器腳本
您可以建立一個包裝啟動命令的進入點腳本,並使用 JSON 格式的 ENTRYPOINT
命令執行該腳本。
✅ 良好:ENTRYPOINT
使用 JSON 格式。
FROM alpine
RUN apk add bash
COPY --chmod=755 <<EOT /entrypoint.sh
#!/usr/bin/env bash
set -e
my-background-process &
my-program start
EOT
ENTRYPOINT ["/entrypoint.sh"]
明確指定 Shell
您可以使用 SHELL
Dockerfile 指令來明確指定要使用的 shell。由於設定 SHELL
指令表示使用 shell 格式是有意識的決定,因此將會抑制此警告。
✅ 良好:已明確定義 shell。
FROM alpine
RUN apk add bash
SHELL ["/bin/bash", "-c"]
ENTRYPOINT echo "hello world"