建議使用 JSON 格式參數 (JSONArgsRecommended)

輸出

JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals

說明

ENTRYPOINTCMD 指令都支援兩種不同的參數語法

  • Shell 格式:CMD my-cmd start
  • Exec 格式:CMD ["my-cmd", "start"]

當您使用 Shell 格式時,可執行檔會以 Shell 的子程序執行,這不會傳遞訊號。這表示在容器中執行的程式無法偵測到 SIGTERMSIGKILL 等作業系統訊號,也無法正確回應它們。

範例

❌ 不良:ENTRYPOINT 指令未收到作業系統訊號。

FROM alpine
ENTRYPOINT my-program start
# entrypoint becomes: /bin/sh -c my-program start

為了確保可執行檔可以接收作業系統訊號,請使用 Exec 格式的 CMDENTRYPOINT,這可讓您將可執行檔作為容器中的主要程序(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"