news 2026/5/1 2:05:28

《100个“反常识”经验16:Docker容器退出,日志里什么都没有》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《100个“反常识”经验16:Docker容器退出,日志里什么都没有》

本期摘要

Docker容器无缘无故退出了,用docker logs一看,空空如也。这不是Bug,是容器的几种“静默死亡”方式:OOM Killer 直接杀死进程、健康检查失败被标记为 unhealthy、宿主机磁盘写满导致无法写入、systemd 的MemoryLimit把容器掐死。这些情况下容器进程来不及写日志就被干掉了。本文从一次真实排查出发,教你看docker inspect的退出码、查系统日志dmesg、定位 OOM 记录、配置合理的资源限制。读完你就能在日志空白时照样找到元凶。

一次让人摸不着头脑的故障

某个微服务容器运行一段时间后就会自动退出,没有报错,没有日志。重启后又能跑一会,然后又退出。

执行:

bash

docker logs --tail 100 app_container

一片空白。容器内部没有任何日志输出,因为进程根本没来得及写到磁盘就被干掉了。

查看容器退出信息:

bash

docker inspect app_container | grep -E "ExitCode|Error|OOMKilled"

输出:

"ExitCode": 137, "OOMKilled": true,

真相大白:容器被 OOM Killer 杀掉了。这不是应用代码问题,是内存限制设置过低。

容器静默退出的常见原因

退出状态含义元凶
退出码 0正常退出进程自己调用exit(0),检查业务逻辑
退出码 137 (137=128+9)收到 SIGKILLOOM 或被手动docker kill
"OOMKilled": true内存不足被杀死容器内存限制太低,或应用内存泄漏
健康检查失败容器状态变为 unhealthy探针配置不当或依赖服务不可用
宿主机磁盘满容器无法创建日志/文件磁盘写满导致容器异常退出
systemdMemoryLimit宿主机 cgroup 限制systemd 的 MemoryLimit 小于容器限制
app 自身崩溃退出码非0无日志日志未配置 stdout/stderr,或写入磁盘失败

排查步骤

第一步:查看容器退出信息

bash

docker inspect <container_id> | jq '.[0].State'

关注字段:

字段含义
ExitCode退出码,137=SIGKILL
OOMKilled是否被OOM杀死
Error错误信息
Statusexited / running / dead

第二步:查看系统 OOM 记录

bash

dmesg | grep -i "out of memory" dmesg | grep -i "kill" journalctl -k | grep -i oom

如果看到类似Out of memory: Kill process 12345 (java) score 987的记录,说明宿主机或容器触发了 OOM。

第三步:检查容器资源限制

bash

docker inspect <container_id> | jq '.[0].HostConfig.Memory'

0 表示无限制,否则以字节为单位。确认限制是否合理:

bash

docker stats --no-stream <container_id>

查看实际内存使用量。如果实际使用接近限制,就是内存不足。

第四步:检查宿主机资源

bash

free -h # 内存 df -h # 磁盘 dmesg | tail -20 # 内核日志

磁盘写满也会导致容器异常退出,因为容器无法创建日志文件或写入存储层。

第五步:排查健康检查

bash

docker inspect <container_id> | jq '.[0].State.Health'

健康检查连续失败,容器会被标记为 unhealthy,如果设置了--health-retries且达到阈值,Docker 会 kill 容器并重启(取决于--restart策略)。

常见解决方案

OOM Killed → 限制内存或增加配额

bash

# 调大内存限制 docker run -m 2g ...

宿主机内存不足 → 清理或扩容

bash

# 清理未使用的容器、镜像 docker system prune -a

健康检查失败 → 调整探针参数

yaml

healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 5s retries: 3 start_period: 10s

systemd 限制冲突

在 systemd 启动脚本中:

text

MemoryLimit=2G

确保 systemd 的 MemoryLimit 不小于 Docker 的-m参数,否则 systemd 会在宿主机 cgroup 层面先杀死容器。

日志未输出到 stdout

Docker 的docker logs只能看到输出到 stdout/stderr 的日志。如果应用把日志写到了文件里,需修改日志配置:

python

# Python logging.basicConfig(stream=sys.stdout)

java

// Spring Boot logging.file.name = /dev/stdout # 或使用 application.properties

真实案例

现象排查根因解决
容器跑一会就退出,日志为空docker inspect显示 OOMKilled=true内存限制 512M,实际需要 800M调大内存限制
重启后立刻退出docker logs无输出,dmesg看到 disk quota exceeded宿主机 /var 分区写满清理磁盘空间
容器状态不断 unhealthy-restartHealth字段看到连续失败健康检查的/health依赖数据库修改健康检查,或先启动依赖服务
容器无日志,出现在 systemd 日志journalctl -u docker看到 MemoryLimit 冲突systemd 限制比容器小对齐两者限制

永久防范方案

  • 合理设置内存和 CPU 限制,预留 20% 余量

  • 监控宿主机磁盘和内存,建立告警

  • 确保应用日志输出到 stdout/stderr

  • 健康检查不要依赖外部服务(数据库/Redis)

  • 设置合理的--restart策略

下期预告

《100个“反常识”经验17:服务器被挖矿了,我第一反应不是kill》

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 2:05:25

EN50332标准解析:便携音频设备声压级测量与听力保护

1. EN50332标准与声压级测量基础1.1 标准背景与听力保护需求便携式音频设备的普及带来了听力健康隐患。根据世界卫生组织数据&#xff0c;全球约11亿年轻人面临噪声性听力损失风险&#xff0c;其中个人音频设备的不当使用是主要诱因之一。EN50332标准正是欧盟针对这一问题的技术…

作者头像 李华
网站建设 2026/5/1 1:55:36

守护应急每一刻|江苏翠苗新材料应急推车,实用更靠谱!

守护应急每一刻&#xff5c;江苏翠苗新材料应急推车&#xff0c;实用更靠谱&#xff01;在应急救援、物资转运、医疗值守、工厂车间、校园商超等各类场景中&#xff0c;一台好用的应急推车&#xff0c;就是高效处置、快速响应的关键帮手。江苏翠苗新材料深耕防护包装与应急装备…

作者头像 李华
网站建设 2026/5/1 1:54:55

用 EFR32 实现低功耗蓝牙传感器节点(从原理到实战)

&#x1f50b; 用 EFR32 实现低功耗蓝牙传感器节点&#xff08;从原理到实战&#xff09;做 IoT&#xff0c;如果设备只能跑一天&#xff0c;那就是“玩具”。 能跑一年&#xff0c;才叫“产品”。 本文带你用 EFR32 做一个&#xff1a; &#x1f449; 低功耗 BLE 传感器节点 具…

作者头像 李华