码头工人停止睡眠 bash 脚本



我有作为docker入口点运行的bash脚本。

此脚本执行一些操作,然后进入睡眠状态。

我需要能够在发出命令时优雅地停止此脚本docker stop。AFAIK docker 向进程 1 发送SIGTERM信号。

所以我创建了对SIGTERM做出反应的 bash 脚本。

没有 docker 它可以正常工作,我可以启动它,发出kill -TERM <pid>,它会优雅地停止脚本。不幸的是,它在码头工人中不起作用。

Dockerfile:

FROM ubuntu:20.04
WORKDIR /root
COPY test.sh .
CMD ./test.sh

test.sh:

#!/bin/sh
trap 'echo TERM; exit' TERM
sleep 1 &
while wait $!
do
sleep 1 &
done

我应该如何修改脚本或 Dockerfile 以允许 docker stop 正常工作?

请注意,我不允许将-it参数传递给docker run

问题来自CMD指令的shell 形式CMD ./test.sh

在这种情况下,命令使用/bin/sh -cshell 执行。所以/bin/shPID 1运行,然后分叉test.shPID 1/bin/sh -c ./test.sh。结果,SIGTERM信号被发送到PID 1并且永远不会到达test.sh

要更改此设置,您必须使用exec 表单CMD ["./test.sh"]。在这种情况下,该命令将在没有外壳的情况下执行。因此,信号将到达您的脚本。

FROM ubuntu:20.04
WORKDIR /root
COPY test.sh .
CMD ["./test.sh"]

跑和杀。

# run
docker run -d --name trap trap:latest
# send the signal
docker kill --signal=TERM trap
# check if the signal has been received
docker logs trap
# TERM

我建议你尝试使用docker kill --signal=SIGTERM <CONTAINER_ID>

请让我知道它是否有效。

请注意,如果您的脚本碰巧生成子进程,您可能会在 docker 退出时留下孤立进程。尝试使用 --init 标志运行,如docker run --init ...,内置的docker-init可执行文件tini将假定为 pid 1,并确保所有子进程(例如您的睡眠示例)将在退出时相应地终止。

最新更新