为何sudo kill -15终止sh与docker-compose进程无法停止Docker容器?
问题描述
使用以下命令启动Docker容器:
sudo -E env PATH="$PATH" sh -c "docker-compose up"
通过ps aux查看进程层级,结果如下:
root 2505477 0.1 0.0 7916 3788 pts/4 S+ 06:46 0:00 sudo -E env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin sh -c docker-compose up root 2505480 0.0 0.0 7916 520 pts/5 Ss 06:46 0:00 sudo -E env PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin sh -c docker-compose up root 2505481 0.0 0.0 2316 816 pts/5 S+ 06:46 0:00 sh -c docker-compose up root 2505483 6.6 0.5 351976 48552 pts/5 Sl+ 06:46 0:00 /usr/bin/python3 /usr/bin/docker-compose up
进程树结构如下:
sudo(2505477)───sudo(2505480)───sh(2505481)───docker-compose(2505483)─┬─{docker-compose}(2505755) ├─{docker-compose}(2505756) └─{docker-compose}(2505757)
出现的异常现象:
- 执行
sudo kill -15 2505481 2505483同时终止sh进程(PID 2505481)和docker-compose进程(PID 2505483)时,Docker容器并未停止; - 仅执行
sudo kill -15 2505483终止docker-compose进程时,容器可正常停止。
疑问:为何同时终止两个进程无法停止Docker容器?
技术分析
核心原因在于**docker-compose up的容器停止逻辑依赖自身完整的信号处理流程,同时终止父进程sh会直接打断这个流程**,具体拆解如下:
- 单独终止docker-compose的正常流程
当只向docker-compose进程(PID2505483)发送SIGTERM(-15信号)时,它会触发内置的优雅关闭逻辑:
- 主动向管理的所有Docker容器发送
SIGTERM信号,请求容器优雅停止; - 等待容器完成资源清理、进程退出等操作后,自身再正常退出,整个流程完整执行。
- 同时终止sh和docker-compose的异常情况
当同时给sh(PID2505481)和docker-compose发送SIGTERM时,两个进程几乎同时收到信号:
- sh作为docker-compose的父进程,收到信号后会直接退出,不会等待子进程执行完成;
- docker-compose刚收到
SIGTERM,还没来得及完成向容器发信号的操作,就因为父进程退出被Linux的孤儿进程机制接管(init/systemd成为新父进程); - 更关键的是,docker-compose的信号处理依赖当前的终端/stdin/stdout环境,而sh进程退出会直接关闭这些资源,导致docker-compose的停止逻辑中途崩溃,最终可能直接退出却没触发容器停止的核心操作。
- 进程层级的次要影响
进程树中的两层sudo不是核心问题,核心矛盾还是父进程sh的突然退出破坏了docker-compose的执行环境,导致它无法完成容器停止的完整流程。
总结:docker-compose的容器停止逻辑需要自身进程存活足够时间来完成信号发送和状态等待,同时终止父进程sh会瞬间破坏其执行环境,使得它来不及完成容器停止操作。
内容的提问来源于stack exchange,提问作者Shivam Jha
相关产品推荐
相关产品推荐

