首页/云/Docker 容器速查/容器 OOM 的识别与处理
资源与安全50 条

容器 OOM 的识别与处理

容器内存超限被内核终止时:退出码 137、inspect 的 OOMKilled 为 true;处理顺序是先确认限制值与峰值,再决定调限额或降内存。

Docker 容器速查云更新于 2026-10-13

容器 OOM 是什么

给容器设置了内存上限后,进程申请的内存超过上限时,内核会触发 OOM 终止流程,通常直接杀掉容器内最占内存的进程,容器随之退出。识别特征很明确:退出码是 137,容器状态里带 OOM 标记。处理不是简单地把上限调大,而是先判断用量是正常峰值还是持续增长,再决定调限额、修内存泄漏还是调整运行时堆参数。

基本信息

典型退出码137,表示 128 加 SIGKILL
判定字段.State.OOMKilled 为 true
内存上限字段.HostConfig.Memory(字节)
宿主侧记录dmesg 中与内存终止相关的记录
相关参数--memory 设上限、--memory-swap 控制交换、--oom-kill-disable 关闭终止(谨慎使用)
观察工具docker stats、容器内应用的自己指标

典型使用场景

  • 服务反复重启且日志无异常:确认是否被内存终止
  • 大内存任务中途失败:核对峰值是否超过限额
  • 排查内存泄漏:观察限额固定而用量持续爬升
  • 容量规划:根据稳定用量设置合理上限,避免一味放大
  • Java 类服务调参:上限与堆参数需要配套调整

判定与取证

判定与取证
# 一、退出码与 OOM 标记:两条要一起看
docker inspect -f 'exit={{.State.ExitCode}} oom={{.State.OOMKilled}} limit={{.HostConfig.Memory}}' api

# 二、容器与宿主的事件记录
docker events --filter container=api --filter event=oom --since 24h
dmesg | grep -i -E 'oom|killed process' | tail -20

# 三、用量观察:看长期趋势而不是单点
docker stats --no-stream api

# 四、限额与交换空间的配置
docker run -d --memory 512m --memory-swap 1g --name api app/api:1.4.2

结果判读

线索结论处理方向
137 且 OOMKilled=true容器内存超限调上限或修内存增长
137 且 OOMKilled=false宿主内存紧张或人为终止查看宿主日志与操作记录
用量锯齿状上升后归零周期性任务峰值超限错峰或提高上限
用量缓慢持续上升疑似内存泄漏抓取长期样本定位
限额很高仍被终止宿主整体容量不足评估宿主与同机服务

调整与验证

调整与验证
# 调大上限后重建容器(改运行参数必须重建)
docker rm -f api
docker run -d --memory 1g --name api app/api:1.4.2

# 验证限额已生效:Memory 字段应等于新上限
docker inspect -f '{{.HostConfig.Memory}}' api

# 压测期间持续观察,确认稳定用量与峰值都有余量
docker stats --no-stream api
关闭 OOM 终止能力(--oom-kill-disable)只在容器已设置内存上限且有明确理由时才讨论,它会让内存压力转嫁给宿主其他进程,通常不是好选择。
按整机内存推导堆大小的运行时会忽略容器限额:Java、Node 之类的服务在被限内存后仍可能申请过多内存,限制上限时要同时调小应用的堆参数。

易错点

  • 137 也可能来自停止超时或人为终止,必须用 OOMKilled 字段区分,否则会反复调整无效参数
  • 只看应用日志会误判成程序崩溃,容器被强制终止时日志往往直接截断,先看退出码与标记
  • 给按宿主内存计算的应用限内存却不调堆参数,容器刚启动就触碰上限反复重启
  • 宿主整体内存紧张时的终止不算容器超限,需要看宿主日志与同机其他服务的占用

数据来源与参考

  • Docker 官方文档:OOM 与资源限制(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌