【问题标题】:Docker stop sleeping bash scriptDocker停止睡眠bash脚本
【发布时间】:2021-12-11 12:50:34
【问题描述】:

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

这个脚本做了一些事情然后休眠。

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

所以我创建了响应 SIGTERM 的 bash 脚本。

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

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

【问题讨论】:

  • 不是 Bash 脚本,它由 /bin/sh 执行,这是一个 POSIX shell,而不是 Bash。
  • 容器实际上应该做什么?你可以删除睡眠循环,让容器在其主进程完成时退出吗? (考虑使用docker run --rm 选项启动容器,这样它就会自行删除。)

标签: linux bash docker sh


【解决方案1】:

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

请让我知道它是否有效。

【讨论】:

  • 感谢您的建议,很遗憾没有任何反应。
【解决方案2】:

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

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

要更改这一点,您必须使用 执行表单CMD ["./test.sh"]。在这种情况下,该命令将在没有 shell 的情况下执行。所以信号会到达你的脚本。

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2012-04-07
      • 2018-02-20
      • 1970-01-01
      • 2015-06-28
      • 2010-12-09
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多