Docker 容器产生的标准输出与标准错误日志,由日志驱动负责处理和存储。默认的 json-file 驱动将每一行日志封装为 JSON 对象写入宿主机文件,虽然便于使用 tail 等命令直接查看,但它本身不会自动轮转或清理。当容器长期运行、访问量较高或应用打印大量调试信息时,日志文件可能持续增长,最终占满整个系统盘。要避免这类故障,需要从理解日志驱动类型开始,并在全局或容器级别配置合理的轮转与限制策略。

一、Docker内置日志驱动的类型与差异
Docker 引擎内置了多种日志驱动,可通过 docker info | grep Logging 查看当前默认驱动。常见驱动包括 json-file、local、syslog、journald、fluentd、awslogs 等。每种驱动背后对应不同的日志转发与存储逻辑。json-file 驱动将日志以 JSON 行形式写入宿主机目录 /var/lib/docker/containers/<id>/<id>-json.log,优点是可以直接 tail 查看,缺点是未配置轮转时文件会无限增长。
local 驱动从较新版本开始提供,采用私有存储格式并内建文件大小与数量限制,适合生产环境长期运行。syslog 与 fluentd 驱动则会把日志发送到远端收集系统,宿主机本地不会留存大量数据。选择驱动时要综合考虑磁盘压力、排查便利性和日志集中化需求。容器数量少且需要频繁登录机器查看日志时,可以为 json-file 增加限制参数;宿主机磁盘小、容器多时,local 驱动更稳妥;团队已有集中式日志平台时,使用 fluentd 驱动可以避免二次采集。
日志驱动既可以在 Docker daemon 级别配置,也可以在单个容器启动时指定。容器启动时通过 --log-driver 与 --log-opt 传入的参数优先级高于全局配置,这为治理个别日志量特别大的容器提供了灵活手段。
二、使用 daemon.json 进行全局日志配置
修改 /etc/docker/daemon.json 是最常用的全局配置方式。该文件是 Docker 守护进程的启动配置,修改后需要执行 systemctl restart docker 使其生效。下面的示例将默认驱动改为 local,并限制每个容器最多保留 3 个文件、单文件 10MB。
{
"log-driver": "local",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
如果希望继续使用 json-file 驱动但避免磁盘被写满,同样可以加入限制参数,只是文件中保存的仍是明文 JSON。下面的配置限制单文件 50MB、最多保留 5 个文件,超出后 Docker 会自动轮转并删除最旧文件。
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
}
}
全局配置的优势在于一次设定即可让所有新容器受益,不必改动既有容器的启动脚本。但它的局限也很明显:无法为不同业务容器设定不同策略,而且修改后只对新建容器生效,旧容器需要重建才能应用新驱动。因此在已有大量运行中容器的宿主机上做切换时,需要提前规划迁移方案。
max-size 定义单个日志文件达到多大时触发轮转,支持 k、m、g 等容量单位;若不设置,json-file 默认不限制大小。max-file 设置保留的文件总数,包含正在写入的那个文件,超出数量后旧文件会被自动删除。对于 local 驱动,还可以使用 compress 参数开启压缩,进一步降低磁盘占用。需要注意的是,log-opts 中的键名取决于具体驱动,例如 fluentd 驱动使用 fluentd-address 而不是通用的 max-size。配置错误可能导致 Docker 守护进程启动失败,因此修改 daemon.json 前建议先执行 dockerd --validate 做静态校验。
三、容器级日志驱动配置与验证
当某个特定容器日志量远超其他服务时,可以在 docker run 时单独指定驱动和参数。以下命令启动一个 Nginx 容器,使用 json-file 驱动并收紧到单文件 20MB、保留 2 份,避免其访问日志把磁盘写满。
docker run -d --name nginx-demo --log-driver json-file --log-opt max-size=20m --log-opt max-file=2 -p 8080:80 nginx:stable
对于需要把日志直接发送到远程收集器的场景,可以采用 fluentd 驱动。下面示例将容器日志发往本机 24224 端口的 Fluentd 服务,并打上服务标签便于后端过滤。
docker run -d --name app-logtest --log-driver fluentd --log-opt fluentd-address=127.0.0.1:24224 --log-opt tag=docker.app.demo busybox echo "hello logging"
容器级配置让运维人员能够精细控制单个服务的日志行为,但也会增加编排文件或启动脚本的复杂度。在 Kubernetes 等容器编排环境中,通常不直接依赖 Docker 日志驱动,而是通过节点级采集组件或 Pod 日志配置来实现统一收集,这与单机 Docker 的使用习惯有所不同。
配置完成后,可以使用 docker inspect 命令确认容器实际采用的驱动与参数。重点关注 HostConfig.LogConfig 字段,它会显示 Type 与 Config 信息。下面的命令可以输出指定容器的日志配置。
docker inspect -f '{{.HostConfig.LogConfig}}' nginx-demo
这条命令通常会输出类似 {json-file map[max-file:2 max-size:20m]} 的结果。通过比对实际值与预期值,可以快速定位为什么某个容器仍然产生超大日志文件。例如单位写成了 mb 而不是 m,Docker 可能无法正确解析,导致限制失效。发现配置不符合预期时,要检查 daemon 是否已重启、启动命令是否被覆盖,以及参数拼写是否正确。
四、日志清理误区与磁盘保护实践
不少运维人员在磁盘报警后才去删除 -json.log 文件,但直接执行 rm 并不能真正释放磁盘空间,因为 Docker 进程仍然持有该文件的句柄。正确的处理方式是在删除或轮转之前,先使用 truncate -s 0 清空文件内容,再视情况重启容器释放句柄。更好的做法是提前配置好轮转参数,避免进入事后救火的被动局面。
另一个常见误区是认为更换为 local 驱动后就能绝对安全。local 驱动虽然内置了限制机制,但如果 max-file 设置得过大、单文件容量也很大,在极端日志爆发期间仍可能短期占满磁盘。因此建议为 /var/lib/docker 所在分区配置容量监控与告警,一旦使用率超过阈值就及时介入处理。
从 json-file 驱动迁移到 local 驱动时,旧容器的历史日志不会自动转换格式。需要先将容器日志目录归档保存,再删除容器并以新驱动重建。若业务不允许中断,可以采用蓝绿部署方式:先启动新版本容器并指定 local 驱动,验证日志输出正常后,再下线旧容器,从而平滑完成驱动切换。综合来看,Docker 日志驱动配置并不是一次性动作,而是随着业务规模演进需要持续调优的过程。只有理清不同驱动的差异、合理组合全局与容器级参数,并建立容量监控与告警机制,才能从根本上避免日志文件将系统盘撑爆的事故。