Docker容器运行Shell脚本忽略SIGTERM无法正常停止的问题
Docker容器无法用
docker stop停止的解决方案 问题根源
当容器以bash /app/demo.sh作为启动命令时,bash进程会成为容器内的PID 1。Linux环境中,PID 1进程默认不会自动转发信号给子进程,且bash作为PID 1时,对docker stop发送的SIGTERM信号没有默认处理逻辑,导致后台的sleep进程收不到停止信号,容器只能等待超时后被强制杀死。
解决方案
方案1:修改脚本添加信号捕获
修改demo.sh,通过trap命令捕获SIGTERM信号,主动终止sleep进程:
#!/bin/bash cleanup() { echo "Received stop signal, terminating sleep..." kill "$sleep_pid" exit 0 } # 注册SIGTERM信号处理函数 trap cleanup SIGTERM echo "Test 123.." # 将sleep放入后台运行并记录PID sleep 5m & sleep_pid=$! # 等待sleep进程结束 wait "$sleep_pid" echo "After sleep"
方案2:让脚本成为PID 1进程
修改Dockerfile的CMD指令,使用exec让脚本直接成为容器的PID 1,这样bash会正确响应SIGTERM信号:
CMD ["exec", "bash", "/app/demo.sh"]
或者直接执行脚本(需保证脚本开头的#!/bin/bash有效):
CMD ["/app/demo.sh"]
方案3:使用tini作为初始化进程
在Dockerfile中安装tini,让它作为PID 1负责信号转发,确保所有子进程能收到停止信号:
# syntax=docker/dockerfile:1.4 FROM alpine:3 WORKDIR /app RUN apk add --no-cache \ curl bash sed uuidgen tini COPY demo.sh /app/demo.sh RUN chmod +x /app/*.sh ENTRYPOINT ["tini", "--"] CMD ["bash", "/app/demo.sh"]
内容的提问来源于stack exchange,提问作者kiler129
相关产品推荐
相关产品推荐

