Exit Code 137 Docker容器意外退出内存不足OOM Killed怎么排查?

文章导读
Docker 容器退出码 137 通常意味着进程被系统内核的 OOM Killer 强制终止,最直接的排查方向是检查容器内存限制与宿主机可用内存,优先通过 docker inspect 确认 OOMKilled 状态。
📋 目录
  1. 核心原理:为什么是 137
  2. 排查步骤与命令
  3. 解决方案:调整内存限制
  4. Java 应用特别注意事项
  5. 验证与常见坑
A A

Docker 容器退出码 137 通常意味着进程被系统内核的 OOM Killer 强制终止,最直接的排查方向是检查容器内存限制与宿主机可用内存,优先通过 docker inspect 确认 OOMKilled 状态。

先说结论:退出码 137 大概率是内存超限被杀,先查容器状态字段,再调内存限制,最后验证稳定性。

  • 先确认:检查 docker inspect 中的 OOMKilled 字段是否为 true
  • 先处理:调整容器内存限制 -m 或优化应用内存占用
  • 再验证:监控内存水位并观察容器是否再次异常退出

核心原理:为什么是 137

退出码 137 并非应用主动报错,而是被动终止。按照 Shell 约定,退出码 128 以上代表被信号杀死,137 即 128 加 9,对应 SIGKILL 信号。在 Docker 环境中,这通常是因为容器内进程消耗的内存超过了设定的上限,触发了 Linux 内核的 OOM Killer 机制。即使宿主机仍有空闲内存,如果容器被限制了内存配额,超出配额后依然会被强制杀死。

排查步骤与命令

第一步,确认是否为 OOM 导致。运行以下命令查看容器状态,重点关注 ExitCode 是否为 137 且 OOMKilled 字段是否为 true。

Exit Code 137 Docker容器意外退出内存不足OOM Killed怎么排查?
docker inspect <container_name> `--format`='{{json .State}}'

如果 OOMKilled 为 false 但退出码是 137,需进一步检查系统 dmesg 日志确认是否有内核杀进程记录。

dmesg -T | grep -i "killed process"

第二步,检查内存限制与使用量。使用 docker stats 查看容器实时内存占用,对比启动时设置的 -m 参数。

docker stats

解决方案:调整内存限制

根据容器状态不同,调整方式有所区别:

Exit Code 137 Docker容器意外退出内存不足OOM Killed怎么排查?

1. 运行中的容器(临时调整)
可以使用 docker update 命令动态调整内存限制,无需重启容器(部分内核版本可能需要重启生效):

docker update `--memory`=4g <container_name>

2. 新建容器
在启动时通过 -m 参数指定内存上限:

docker run -d -m 4g `--name` my_app my_image

3. Docker Compose 配置
在 docker-compose.yml 中通过 mem_limit 或 deploy 资源配置:

Exit Code 137 Docker容器意外退出内存不足OOM Killed怎么排查?
version: '3'
services:
  web:
    image: my_image
    mem_limit: 4g
    # 或者使用 deploy 配置(Swarm 模式)
    # deploy:
    #   resources:
    #     limits:
    #       memory: 4g

Java 应用特别注意事项

对于 Java 应用,仅调整 Docker 内存限制而不调整 JVM Heap 可能导致问题依旧。Docker 限制的是容器总内存,JVM 堆内存只是其中一部分。建议将 JVM 最大堆内存设置为容器限制的 70%-80%,预留空间给非堆内存。

# 示例:容器限制 4g,JVM 堆设置为 3g
java -Xmx3g -jar app.jar

验证与常见坑

验证方法:调整后重启容器,观察一段时间内是否再次出现 Exited 状态。通过 docker ps -a 查看容器退出码是否回归 0 或正常业务退出码。同时持续监控 dmesg 日志,确认不再出现新的 killed process 记录。对于 Java 或 Python 服务,观察内存曲线是否不再持续飙升后归零。

常见坑:

  • 不是所有 137 都是 OOM,若 docker inspect 显示 OOMKilled 为 false,可能是用户手动执行 docker kill 或守护进程问题。
  • PHP 应用中容易忽略 CLI 与 Web 环境的 memory_limit 配置不一致,导致命令行任务意外终止。
  • 宿主机启用 Swap 会影响所有容器及系统性能。仅在紧急情况下临时启用 Swap 作为兜底(注意:会影响宿主机所有容器性能,仅建议临时应急),频繁使用会导致性能下降,不能替代真正的内存调优。
  • SSD 上频繁使用 Swap 会导致 Composer 等 IO 敏感型任务极慢,需谨慎启用。