Docker 容器启动失败 exit code 137 怎么优化

文章导读
遇到容器启动失败,退出码是 137,我一般不会先去调整内存限制,而是先确认这次退出到底是被谁终止的。下面是我的排查记录,尽量把每一步的适用场景和验证方式都说清楚。
📋 目录
  1. A 先确认现象
  2. B 容易误判的地方
  3. C 建议的处理顺序
  4. D 调整容器内存上限
  5. E 从应用层确认内存占用
  6. F 验证、回滚与后续维护
A A

遇到容器启动失败,退出码是 137,我一般不会先去调整内存限制,而是先确认这次退出到底是被谁终止的。下面是我的排查记录,尽量把每一步的适用场景和验证方式都说清楚。

先确认现象

容器以 exit code 137 退出,通常表示进程被 SIGKILL 信号终止,最常见原因是容器或宿主机内存不足,触发了内核的 OOM Killer。判断时先看 dmesg 或 journalctl 中是否有 Out of memory 记录,也可以直接运行 docker inspect 查看容器的 State.OOMKilled 字段。如果该字段为 true,基本可以确认是内存资源耗尽,而不是应用自身崩溃。

这一步能帮你省掉很多无意义的调优动作。OOMKilled 为 true 时,优先排查内存水位;为 false 时,再去检查 dmesg 里有没有手动 kill 相关记录。

容易误判的地方

不是所有 137 都是 OOM。手动执行 kill -9 同样会让退出码变成 137,宿主机重启或系统清理进程时也可能出现类似现象。

还有一种容易被忽略的情况:OOM Killer 选中的不一定是当前容器的主进程。如果 dmesg 里看到被杀的是宿主机上的其他进程,而当前容器也退出了 137,那代表整个宿主机的内存压力已经很高,只是当前容器恰好在这个时间点崩溃。

Docker 容器启动失败 exit code 137 怎么优化

建议的处理顺序

我建议的顺序是:先看日志,再判断是容器限制问题还是应用自身内存问题,最后才动手调参数。

  1. 查看宿主机日志:dmesg -T | grep -i oom,确认是否有内存耗尽记录。
  2. 查看容器状态:docker inspect <容器名> --format='{{.State.OOMKilled}}',快速确认是否被 OOM。
  3. 进入容器看实际内存占用:docker statstop,观察是哪个进程占得高。

这个顺序别颠倒。先调大内存是止血,但没找到根因,下次换一个时间点还会崩。

调整容器内存上限

如果确认是 OOM,常见做法是提高容器内存上限。在 docker run 时通过 --memory 和 --memory-swap 调整,比如原来限制 512m,可以逐步增大到 1g 或 2g。需要注意 --memory-swap 默认与 --memory 相等,若不设置 swap,容器无法借用交换分区。提高后观察一段时间的稳定性,不要一次调太大,避免宿主机其他服务被影响。

Docker 容器启动失败 exit code 137 怎么优化

一个典型的调整示例:

docker run -d --name app --memory=1g --memory-swap=1g nginx

如果容器原本没有设置 --memory,那就代表容器本身没有内存限制,但宿主机内存不足时依然会触发 OOM。这种情况下要先看宿主机可用内存,而不是一味地给容器加限制。

从应用层确认内存占用

很多情况下 137 不是容器限制太小,而是应用自身占内存过多。以 Java 应用为例,需要检查堆内存设置是否合理,比如 -Xmx 是否接近容器内存上限,还预留了堆外内存和线程栈的空间。其他语言同样要关注进程的 RSS 和虚拟内存。建议先进入容器执行 top 或 cat /proc/1/status 查看实际占用,再决定是调优应用还是调大容器。

比如 Java 服务,如果 -Xmx 已经设为 1g,容器限制也是 1g,那堆外内存、元空间和线程栈稍有波动就容易撞到上限。比较稳妥的做法是给 JVM 留出额外余量,但具体留多少需要结合 JDK 版本和容器里的实际占用确认。

Docker 容器启动失败 exit code 137 怎么优化

验证、回滚与后续维护

调整之后,要观察的不只是容器能不能起来,还要看运行一段时间后内存走势。可以用 docker stats 连续查看,或者让容器处理一段日常请求,确认内存没有持续增长。

如果调大后容器反而被杀得更频繁,先检查宿主机物理内存是否足够。宿主机上还有别的服务时,给一个容器调大上限,很可能挤占其他服务的资源。通过 --oom-score-adj 降低关键容器被杀概率是最后手段,但这个参数会影响宿主机整体的 OOM 选择逻辑,需要结合环境确认能否接受。

回滚也很直接:把 --memory 参数改回原值,重新创建容器即可。如果是应用层参数调优失败,就恢复原有的 -Xmx 或对应配置。长期来看,建议把容器内存、应用内存和宿主机内存分开监控,出现 137 时能立刻定位是哪一个维度先到极限。不要依赖容器的重启策略来掩盖 137,反复重启通常说明内存压力一直存在,问题不是重启能解决的。