如何为docker stop定义容器退出执行点?解决Tomcat关机逻辑不执行问题
Docker中
docker stop未触发Tomcat自定义关机逻辑的解决方法 1 docker stop 工作机制
- 执行
docker stop <容器名>时,Docker守护进程首先向容器的1号进程发送SIGTERM信号 - 等待用户指定的超时时间(默认10秒,
-t参数可自定义)后,如果1号进程仍未退出,将发送SIGKILL信号强制杀死所有容器内进程 - 你遇到的核心问题是:Tomcat进程没有收到
SIGTERM信号,因此不会触发正常的关机流程,自然不会执行临时文件转CSV的逻辑
2 问题根因
绝大多数场景下该问题是由容器1号进程的启动方式导致的:
如果你在Dockerfile中使用shell形式的ENTRYPOINT/CMD,比如:
ENTRYPOINT /usr/local/tomcat/bin/catalina.sh run
此时容器的1号进程是sh外壳,而sh默认不会转发SIGTERM信号给子进程(也就是Tomcat进程),导致Tomcat收不到关机通知,超时后直接被SIGKILL强制终止。
3 解决方案
方案1:使用exec形式启动Tomcat(推荐)
将Dockerfile中的ENTRYPOINT/CMD改为exec数组形式,让Tomcat直接成为容器1号进程,就能直接接收SIGTERM信号触发正常关机:
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh", "run"]
如果使用自定义启动脚本做前置初始化,在脚本最后启动Tomcat时加exec前缀,让Tomcat替换当前shell进程成为1号进程:
# 你的自定义初始化逻辑 # ... # 启动Tomcat exec /usr/local/tomcat/bin/catalina.sh run
方案2:在自定义启动脚本中注册信号处理逻辑
如果你需要保留shell作为1号进程,可在启动脚本中主动捕获SIGTERM信号,触发Tomcat关机脚本:
#!/bin/bash # 自定义entrypoint.sh # 捕获SIGTERM信号,执行Tomcat关机逻辑 trap '/usr/local/tomcat/bin/shutdown.sh' SIGTERM # 后台启动Tomcat /usr/local/tomcat/bin/catalina.sh start # 等待Tomcat进程退出 wait $!
4 额外注意事项
- 确认你的临时文件转CSV逻辑的实际耗时,将
docker stop -t的超时时间设置为大于逻辑执行耗时,例如转换需要15秒时,执行docker stop -t 20 <容器名>,避免未执行完成就被强制杀死 - 可以先进入运行中的容器,手动执行
kill -SIGTERM <Tomcat进程ID>验证关机逻辑是否正常触发,排除业务代码自身的问题
内容的提问来源于stack exchange,提问作者Anish Barot
相关产品推荐
相关产品推荐

