Docker 系列(四十四):容器诡异退出的 137 码

最近发生了一件诡异的事:跑在一台测试服务器上的一个 Tomcat 的 Docker 容器隔几天都会以 ExitCode: 137 退出。最近几天一直很平稳,没有一个容器退出过,直到今天早上 10 点左右,这台机上所有 Tomcat 容器都一起停掉了(除了两个加了 restart=always 的已经自启了)。

137 意味着什么

容器的退出码 137 等于 128 + 9,表示容器内的主进程收到了 SIGKILL 信号而被强制终止。SIGKILL 的来源通常有两类:

  • 内核 OOM killer:宿主机或容器内存不足,内核选中并强制杀掉了进程,此时 docker inspect 中会看到 OOMKilled: true;
  • 人为或外部工具执行了 kill -9,或者 docker stop 超时后被强制终止。

排查过程

既然是 137,第一个怀疑对象自然是 OOM。先用 docker inspect 查看容器的状态:

docker inspect <container_id> --format '{{json .State}}'

输出中 ExitCode 为 137,但 OOMKilled 字段是 false,说明容器并不是被 Docker 以 OOM 为由杀掉的。

再查宿主机内核日志,确认有没有 OOM killer 的记录:

dmesg | grep -i "out of memory"
grep -i "killed process" /var/log/messages

两条命令都没有得到任何 OOM 记录。接着又检查了 Tomcat 自身的日志、系统的定时任务(crontab -l 与 /etc/cron*)以及登录记录(last),都没有发现明显的异常。

分析到这里貌似已经没辙了,如果还有其它方法请在下面留言。

真相

最后我只能想到一个可能性了:公司有一个同事因个人原因在云南远程办公,有可能是被他手动 kill 掉的。确认后果然是他干的(粗暴地把所有 java 进程都 kill -9 了:()。

小结

回过头看,这次 137 退出并不是 OOM kill:OOMKilled 为 false、内核日志里也没有 OOM 记录,而是人为的 kill -9。以后遇到容器以 137 退出,可以按下面的顺序排查:

  1. 先看 docker inspect 的 State.OOMKilled 是否为 true,并确认容器与宿主机的内存占用情况;
  2. 再查内核日志(dmesg、/var/log/messages)中有没有 OOM killer 的记录;
  3. 如果都没有,就要考虑人为的 kill -9 或其他外部强制终止,结合登录记录排查。

日常也建议给容器合理配置内存限制并加上 restart=always——这次要不是有两个容器自启了,服务中断的时间还会更长。

系列导航


   转载规则


《Docker 系列(四十四):容器诡异退出的 137 码》 由 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Docker 系列(四十五):Device or resource busy 排错 Docker 系列(四十五):Device or resource busy 排错
在清理 Docker 数据目录、准备重装时执行了 rm -rf /var/lib/docker,结果报错 Device or resource busy。记录一下原因与解决过程。 现象执行删除命令: rm -rf /var/lib/dock
2023-06-20
下一篇 
Docker 系列(四十三):Nginx 容器实战 Docker 系列(四十三):Nginx 容器实战
Nginx 是开源的高效的 Web 服务器实现,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等协议。官方在 Docker Hub 上维护了官方镜像仓库,提供了 Nginx 1.0 ~ 1.19.x 各个版本的镜像。 启动静态页
2023-06-06
  目录