首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Docker 容器频繁重启排查:OOMKilled、退出码与资源限制实战

Docker 容器频繁重启排查:OOMKilled、退出码与资源限制实战

原创
作者头像
一只特立独行的兔先生
发布于 2026-10-17 16:50:52
发布于 2026-10-17 16:50:52
540
举报

容器莫名重启、docker ps 里 STATUS 总是 Restarting,是线上最常见的问题之一。本文按「先看退出原因,再看资源,最后看应用」的顺序,整理一套可复现的排查流程。

1. 先确认容器为什么退出

代码语言:bash
复制
docker ps -a --filter name=myapp
docker inspect myapp --format '{{.State.ExitCode}} {{.State.OOMKilled}} {{.State.Error}}'
docker inspect myapp --format '{{.RestartCount}} {{.HostConfig.RestartPolicy.Name}}'
  • OOMKilled=true:容器内存超过限制,被内核 OOM killer 杀掉。
  • ExitCode=137:128+9,收到 SIGKILL,常见于 OOM 或被 docker kill。
  • ExitCode=143:128+15,收到 SIGTERM,通常是正常停止,应用没在超时内退出时会被升级为 137。
  • ExitCode=1 / 2:应用自身报错退出,去看日志。
  • ExitCode=126/127:命令无执行权限或找不到,多为 ENTRYPOINT / CMD 写错。

2. 看日志与事件

代码语言:bash
复制
docker logs --tail 200 -t myapp
docker events --since 30m --filter container=myapp
dmesg -T | grep -i -E "killed process|out of memory"

dmesg 中出现 Memory cgroup out of memory 即可确认是 cgroup 内存限制触发。注意:重启后的新容器会覆盖部分现场,所以要尽早采集。

3. 检查资源限制与实际用量

代码语言:bash
复制
docker stats --no-stream myapp
docker inspect myapp --format '{{.HostConfig.Memory}} {{.HostConfig.MemorySwap}} {{.HostConfig.NanoCpus}}'

Memory 为 0 表示未限制。若设置了 -m 512m 而应用堆很大,就会反复 OOM。典型例子是 JVM:

  • 老版本 JDK 不感知容器限制,按宿主机内存估算堆大小;JDK 10+ 默认感知 cgroup。
  • 推荐显式指定比例:-XX:MaxRAMPercentage=70,给堆外内存、线程栈、元空间留出余量。
  • Node.js 可用 --max-old-space-size 限制老生代,避免超出容器上限。

4. 调整限制并设置合理的重启策略

代码语言:bash
复制
docker update --memory 1g --memory-swap 1g myapp
docker run -d --name myapp --memory 1g --restart on-failure:5 myimage:tag
  • --restart always 会掩盖问题并无限重启;排查期建议用 on-failure:N,让故障尽早暴露。
  • Compose 中对应 deploy.resources.limits(Swarm)或 mem_limit,不同 Compose 版本写法有差异,以官方文档为准。

5. 健康检查与启动顺序

容器「起来了但服务不可用」会被编排系统反复拉起。给镜像加健康检查:

代码语言:dockerfile
复制
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD curl -fsS http://127.0.0.1:8080/health || exit 1

--start-period 要覆盖应用冷启动时间,否则启动慢的服务会被误判不健康。依赖数据库、缓存的服务,应用内要有连接重试,而不是启动即退出。

6. 其他常见原因

  • 磁盘满:docker system df 检查镜像、容器、卷占用,必要时 docker image prune。
  • 端口冲突:ss -lntp | grep 8080,日志出现 address already in use。
  • 挂载目录权限:容器内用户 UID 与宿主机目录属主不一致,导致写入失败后退出。
  • 配置文件缺失:环境变量未注入,应用读到空值直接崩溃。

排查清单

  1. docker inspect 看 ExitCode 与 OOMKilled。
  2. docker logs + dmesg 确认直接原因。
  3. docker stats 对比用量与限制,调整应用内存参数而不是只加大限制。
  4. 加健康检查与有限次数的重启策略。
  5. 若在腾讯云 CVM 或容器服务上运行,同时结合云监控的内存、磁盘曲线对照时间点,具体指标以控制台为准。

把退出码、OOM 标记和 cgroup 限制三件事先查清,大多数重启问题几分钟内就能定位。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 先确认容器为什么退出
  • 2. 看日志与事件
  • 3. 检查资源限制与实际用量
  • 4. 调整限制并设置合理的重启策略
  • 5. 健康检查与启动顺序
  • 6. 其他常见原因
  • 排查清单
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档