JSONArgs推荐
目录
输出
JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals
描述
ENTRYPOINT
和CMD
instructions 都支持
参数:
- 壳型:
CMD my-cmd start
- 执行表单:
CMD ["my-cmd", "start"]
当您使用 shell 形式时,可执行文件将作为 shell 的子进程运行,
它不会传递信号。这意味着在
容器无法检测到 OS 信号,例如SIGTERM
和SIGKILL
并响应
他们正确地。
例子
❌ 差:的ENTRYPOINT
command 未接收 OS 信号。
FROM alpine
ENTRYPOINT my-program start
# entrypoint becomes: /bin/sh -c my-program start
要确保可执行文件可以接收作系统信号,请使用 exec 表单CMD
和ENTRYPOINT
,它允许您将可执行文件作为主进程 (PID 1
),避免 shell 父进程。
✅ Good: 的ENTRYPOINT
接收 OS 信号。
FROM alpine
ENTRYPOINT ["my-program", "start"]
# entrypoint becomes: my-program start
请注意,以 PID 1 运行程序意味着程序现在具有特殊的 与 Linux 中的 PID 1 相关的职责和行为,例如收割 子进程。
解决方法
可能在某些情况下,您希望在 shell 下运行容器。
使用 exec 表单时,shell 功能(如变量扩展、管道 (|
)
和命令链接 (,&&
||
、 ) 不可用。要使用这样的
功能,您需要使用 shell 形式。;
以下是您可以实现这一目标的一些方法。请注意,这仍然意味着 可执行文件作为 shell 的子进程运行。
创建包装脚本
您可以创建一个 entrypoint 脚本来包装您的启动命令,并且
使用 JSON 格式执行该脚本ENTRYPOINT
命令。
✅ Good: 的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
形式是一个有意识的决定。
✅ Good:shell 已显式定义。
FROM alpine
RUN apk add bash
SHELL ["/bin/bash", "-c"]
ENTRYPOINT echo "hello world"