退出码137表示容器被sigkill(信号9)强制终止,最常见原因为oom killer触发:若docker inspect显示"oomkilled": true,则是容器超内存limit被cgroup杀;若为false,则多因宿主机全局oom或节点memorypressure驱逐。
退出码 137 表示容器被 sigkill(信号 9)强制终止,最常见原因就是系统触发了 oom killer。它不是应用崩溃,而是内核在内存严重不足时“果断出手”,直接杀进程——不给日志、不等回收、不发警告。排查关键在于确认“谁杀的”以及“为什么杀”。
看容器状态里有没有 OOMKilled 标记
执行:
docker inspect
重点找这一行:
"OOMKilled": true
如果为 true,说明是容器自身超内存 limit 被 cgroup OOM Killer 杀掉;如果为 false,那大概率是宿主机全局 OOM,杀的是整个容器进程树。
查宿主机内核日志找“死亡现场”
OOM Killer 触发后会在内核日志留下明确记录。运行:
dmesg -T | grep -i "killed process"
或
journalctl -k --since "2 hours ago" | grep -i "oom\|kill"
看到类似这样的输出就坐实了:
Out of memory: Kill process 12345 (java) score 897 or sacrifice child
注意后面括号里的进程名和 PID,它往往就是你容器里那个主进程。
核对内存限制与实际使用是否冲突
容器没超 limit 却被杀?常见陷阱有:
• 宿主机 swap 被禁用,导致 cgroup 内存压力无法缓冲
• Java 等应用默认堆外内存(如 DirectByteBuffer、Metaspace)不计入 JVM 堆限制,但会计入容器总内存
• Kubernetes 中设置了 memory limit 但没设 request,调度器可能把 Pod 分配到已满的节点上
• 其他非容器进程(如 logrotate、监控 agent)吃掉了预留内存,挤占了 kubelet 的可用空间
对比容器内存历史与节点资源水位
如果容器还在或刚退出,可快速验证:
• 查容器内存峰值:docker stats
• 查节点整体内存压力:free -h 和 cat /proc/meminfo | grep -E "MemAvailable|MemFree"
• 在 Kubernetes 环境下:kubectl top node 和 kubectl describe node











