Docker容器内sleep状态的bash入口脚本如何响应docker stop优雅停止
问题根因
你遇到的问题来自两个核心原因:
- Docker的
CMD如果使用 shell 形式书写,Docker会自动将其包装为/bin/sh -c "你的命令"执行,此时容器内的PID1进程是这个额外启动的shell,而不是你的test.sh。这个默认的shell不会把收到的SIGTERM信号转发给子进程,导致你脚本里的trap完全收不到信号。 - Ubuntu 20.04默认的
/bin/sh是dash,其wait指令的信号处理逻辑和bash有差异,即使收到信号也可能不会中断等待,导致trap无法触发。
修复方案
1. 修改Dockerfile
把CMD改为 exec 形式,让你的脚本直接作为PID1运行,避免额外的中间shell:
FROM ubuntu:20.04 WORKDIR /root COPY test.sh . # 改为exec数组形式,不会启动额外父shell CMD ["./test.sh"]
2. 修改test.sh脚本
将解释器更换为bash,同时优化信号处理逻辑,收到SIGTERM时同时终止正在运行的sleep子进程,避免残留:
#!/bin/bash # 捕获TERM信号,杀死当前运行的sleep子进程后退出 trap 'echo TERM; kill $sleep_pid 2>/dev/null; exit' TERM while true do sleep 1 & sleep_pid=$! wait $sleep_pid done
修改完成后重新构建镜像运行,执行docker stop时即可触发脚本的优雅退出逻辑,不会出现默认10秒强制杀死的情况,且不需要加-it参数。
内容的提问来源于stack exchange,提问作者vbezhenar
相关产品推荐
相关产品推荐

