跑着跑着,ref="/tag/2019/" style="color:#E3A3CF;font-weight:bold;">Docker容器突然挂了,日志里还留了个“Exited with code 137”,看着挺吓人。其实这问题在开发调试时并不少见,尤其在本地跑服务或者部署测试环境的时候。
退出代码137意味着啥?
简单说,代码137代表容器被系统强制终止了,具体是收到了 SIGKILL 信号(也就是 kill -9)。这种信号不会给进程留喘息机会,直接就杀掉了。而最常见的原因,不是程序本身有 bug,而是——内存不够了。
比如你在笔记本上跑个 Spring Boot 应用加个 MySQL,内存配得紧巴巴的,Docker 一超限,Linux 内核的 OOM Killer(Out-of-Memory Killer)就会出手,干掉最耗内存的那个容器,留下一个 137 走人。
怎么确认是内存问题?
先看容器的资源使用情况:
docker stats <container_id>
如果发现内存使用接近或达到上限,基本就能确定是 OOM 导致的。也可以查系统日志:
dmesg | grep -i 'oom'
如果看到类似 Out of memory: Kill process 1234 (docker-containerd)... 的记录,那就是坐实了。
那该怎么解决?
最直接的办法是给容器多分配点内存。比如启动容器时用 -m 参数限制或提升内存额度:
docker run -d --name myapp -m 2g myimage
上面这行就是给容器分配 2GB 内存。如果你用的是 docker-compose,可以在配置文件里写:
services:
app:
image: myimage
mem_limit: 2g
当然,也别一味加内存。有些应用本身就有内存泄漏,比如 Java 程序没调好 JVM 参数,稍微一压测就爆。这时候应该优化应用,而不是靠堆资源顶着。
其他可能的原因
虽然内存问题是大头,但也不是唯一可能。比如宿主机资源紧张,整个系统都在杀进程保命;或者容器内主进程启动失败,依赖的服务没起来,间接导致崩溃。不过这些通常会伴随其他错误码或日志线索,不像 137 这么“干净利落”。
还有种情况是用了 Kubernetes,Pod 被驱逐或节点资源不足,也会表现为容器退出 137。这时候得去看 kubelet 日志或者事件记录:
kubectl describe pod <pod-name>
总之,看到 137 别急着重跑容器,先查内存、看日志,搞清楚是谁动的手,才能对症下药。