简介:容器长期运行后,标准输出日志可能悄然占满宿主机磁盘。本文系统讲解如何量化定位日志占用、如何在不中断服务的前提下安全清空运行中容器的日志文件,以及如何通过全局与单服务两级日志轮转配置实现治本,并附监控告警与防复发清单,帮你彻底告别磁盘告警。
容器化应用遵循“日志走标准输出”的最佳实践:应用把日志写到 stdout/stderr,由容器引擎的日志驱动统一采集,落盘为宿主机上的一个文件。以最常见的默认驱动为例,日志以 JSON 行格式追加写入单个文件,且默认配置既不限制单文件大小,也不自动滚动。这带来两个直接后果:
因此,治理容器日志的正确姿势是“三步走”:先量化定位,再安全清理(止血),最后配置轮转(治本),并辅以监控防止复发。下文依次展开。
清理前先做“磁盘体检”,避免盲目操作。为保持表述中立,下文用 cli 代指你所使用容器引擎的命令行客户端,用 ENGINE_ROOT 代指引擎的数据根目录(默认通常位于 /var/lib 下以引擎名命名的子目录),请按实际环境替换。
cli system df # 总览cli system df -v # 展开到每个镜像、容器、卷的明细
如果大头不是日志,而是悬空镜像、已停止容器或构建缓存,则应转向清理未使用资源:多数引擎提供 prune 类一键清理子命令,执行前务必确认清理范围,避免误删在用对象。
LogPath 字段):
du -sh $(cli inspect --format '{{.LogPath}}' 容器名)
ENGINE_ROOT/containers 目录下,一行命令即可列出占用前 20 名:
find "$ENGINE_ROOT/containers" -name "*.log" -exec du -sh {} \; | sort -rh | head -20
拿到这份 “Top 20” 清单,通常就能直接锁定肇事容器。
运行中的容器进程长期持有日志文件的打开句柄(文件描述符)。此时执行 rm:
df 看到的可用空间并不会增加;可以用 lsof | grep deleted 验证这一现象:列表里“已删除但仍被占用”的文件,正是那些“删了却没释放”的空间来源。这是该场景下最常见的误区。
truncate -s 0 将文件截断为零字节,但 inode 与文件句柄保持不变,写入方完全无感知,空间立即释放:
truncate -s 0 $(cli inspect --format '{{.LogPath}}' 容器名)
如需一次性处理全部运行中的容器,可批量执行:
for id in $(cli ps -q); dolog_path=$(cli inspect --format '{{.LogPath}}' "$id")truncate -s 0 "$log_path"echo "Cleared: $id"done
执行建议:尽量安排在业务低峰期;对正在高频写入的文件做截断,极端情况下可能出现少量行交错或空洞,对排障影响有限;操作完成后用 df -h 复核空间确已释放。
应急清理只能解一次渴,轮转配置才能长治久安。轮转的核心参数只有两个:单文件上限与保留份数,二者相乘即单个容器的日志空间上限。达到上限时,引擎会将当前文件归档、开启新文件继续写入,超出保留份数的旧文件被删除;在此期间,logs 类命令仍可按顺序查看历史日志。
编辑引擎守护进程的 JSON 配置文件(通常位于 /etc 下以引擎名命名的配置目录中):
{"log-driver": "json-file","log-opts": {"max-size": "50m","max-file": "3"}}
含义:单文件最大 50MB、最多保留 3 份,即单个容器日志最多占用约 150MB(具体字段名以所用引擎文档为准,语义一致)。修改后重载并重启引擎服务使配置生效;部分引擎支持在不停止运行中容器的情况下重启守护进程,可按需开启。
两个关键注意点:
up -d)会自动重建配置发生变化的容器。重建前请确认业务数据已通过数据卷持久化,避免“重建即丢数据”。全局配置给一个保守的兜底值,个别高流量服务再单独放宽。在服务编排文件(YAML)中为对应服务追加日志配置:
services:myapp:image: myapp:latestlogging:driver: "json-file"options:max-size: "100m"max-file: "5"
容量规划的经验法则:接入层、网关等高流量服务给大配额(如 100MB × 5 份),内部轻量服务给小配额(如 10MB × 3 份);更精确的做法是按“峰值日志速率 × 期望保留时长”倒推单服务配额。
若希望容器日志与系统日志合并审计、检索,可将日志驱动切换为 journald。此后日志由系统日志服务接管,自动轮转,并可在系统日志侧配置磁盘占用上限;查询时使用系统日志命令按单元过滤即可(如 journalctl -u <服务单元>)。该方案的取舍在于:统一管理更规范,但检索体验与留存策略需结合宿主机日志规划一并设计。
容器日志治理可浓缩为一套标准动作:先量化(统计命令 + Top 20 定位)、再止血(truncate 而非 rm)、后治本(全局兜底 + 单服务覆盖的两级轮转配置)、常体检(阈值告警 + 定期巡检)。最后牢记两个最容易踩的坑:其一,运行中容器的日志文件不要直接 rm,空间不会释放;其二,日志配置变更后必须重建容器而非仅重启,否则新配置“看起来生效了,实际上没有”。