Docker容器在SSH登录shell断开后无法自动退出的解决方法
解决SSH断开时自动停止Docker容器的方法
核心问题原因
当用户直接关闭终端而非执行exit时,SSH会话会向宿主机上的docker run进程发送SIGHUP信号,但该信号不会自动传递到容器内部的shell进程,导致容器继续后台运行。容器内设置的trap无法捕获到宿主机层面的信号,因此失效。
可行解决方案
方案1:宿主机脚本捕获信号并终止容器
修改/bin/test-shell脚本,让它启动容器后监听会话断开的信号,主动停止容器:
#!/bin/bash # 启动容器并记录后台进程PID docker run -it --rm --init --network none python:3.10-alpine /bin/sh & CONTAINER_PID=$! # 捕获SIGHUP/SIGINT/SIGTERM信号,触发容器停止 trap "docker stop $CONTAINER_PID" SIGHUP SIGINT SIGTERM # 等待容器进程结束,保持脚本运行 wait $CONTAINER_PID
--init参数:让容器内部启动tiniinit进程,负责转发信号给容器内的shell,确保docker stop能快速终止容器。- 脚本通过
trap捕获SSH会话断开时发送的SIGHUP信号,调用docker stop终止对应的容器,容器会因--rm参数自动删除。
方案2:配置SSH会话超时强制断开
在SSH服务端配置中,针对test用户设置会话超时,确保断开后SSH进程能及时退出,触发宿主机脚本的信号捕获:
- 编辑
/etc/ssh/sshd_config,添加以下配置块:
Match User test ClientAliveInterval 10 ClientAliveCountMax 1
- 重启SSH服务:
systemctl restart sshd
ClientAliveInterval 10:每10秒向客户端发送一次存活检测ClientAliveCountMax 1:如果客户端无响应超过1次(即10秒),则主动断开会话
此配置会让SSH在用户终端关闭后快速终止会话,间接触发宿主机脚本的trap逻辑。
方案3:直接关联容器PID与SSH会话
通过docker inspect获取容器的PID,然后让宿主机脚本监控该PID的生命周期:
#!/bin/bash # 启动容器(不后台运行,先记录容器ID) CONTAINER_ID=$(docker run -d --network none python:3.10-alpine /bin/sh) # 获取容器内部PID CONTAINER_INNER_PID=$(docker inspect -f '{{.State.Pid}}' $CONTAINER_ID) # 进入容器终端 docker attach $CONTAINER_ID # 当attach退出后,无论正常还是异常,终止容器 docker stop $CONTAINER_ID
这种方式下,docker attach会直接关联容器终端,当SSH会话断开时,docker attach进程退出,脚本自动执行docker stop。不过需要注意,-d启动容器后再attach,体验和直接-it一致,但能确保后续的停止逻辑执行。
内容的提问来源于stack exchange,提问作者Mia
相关产品推荐
相关产品推荐

