根本解决思路是切断日志对宿主机文件描述符的持续占用,应禁用 docker 日志驱动(logging: driver: "none"),或启用 json-file 轮转(max-size: "10m", max-file: "3"),并排查应用层高频日志根源。

根本解决思路是切断日志对宿主机文件描述符的持续占用,而非单纯清理或调大限制。
关闭服务的标准输出/错误重定向
Compose 默认将容器 stdout/stderr 通过 json-file 驱动写入宿主机磁盘(路径如 /var/lib/docker/containers/*/xxx-json.log),高频日志会快速消耗 inode 和 fd。若服务本身已内置日志轮转或上报能力(如写入 syslog、发到 Loki、打到 stdout 后由采集器处理),可直接禁用 Docker 日志收集:
- 在
docker-compose.yml对应服务下添加:logging: driver: "none"
- 或统一设置默认驱动(适用于全部服务):
services: app: # ... logging: driver: "none"
限制日志大小与保留数量
若仍需保留部分日志用于调试,必须强制启用日志轮转,避免单个日志文件无限增长:
- 配置示例(单个文件最大 10MB,最多保留 3 个旧文件):
logging: driver: "json-file" options: max-size: "10m" max-file: "3" - 该配置作用于容器生命周期,重启后生效;但已有失控的日志文件需手动清理:
truncate -s 0 /var/lib/docker/containers/*/*-json.log(慎用,建议先停对应容器)
检查并优化应用自身日志行为
临时日志刷屏往往源于应用层问题,如未捕获的异常循环打印、健康检查日志级别设为 DEBUG、或轮询逻辑无休眠:
- 确认日志级别是否合理(例如 Spring Boot 的
logging.level.root=INFO,非DEBUG) - 检查是否有类似
while (true) { log.info("ping"); Thread.sleep(10); }的低延迟打点代码 - 使用
docker logs -f --tail=50 service_name实时观察原始输出,定位高频日志源头
补充:临时缓解与监控手段
在彻底修复前,可快速释放资源并建立预警:
- 执行
lsof -nP +D /var/lib/docker/containers/ | grep deleted | wc -l查看被删除但未释放的句柄数(常见于日志文件被 truncate 后进程未 reload) - 重启相关容器(而非仅
docker-compose restart),确保日志文件句柄完全释放 - 在宿主机部署简单监控:
watch -n 5 'ls -l /proc/*/fd/ 2>/dev/null | grep json.log | wc -l'跟踪实时占用量










