DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Docker 修改日志大小上限后,旧容器的 json-file 日志仍持续增长

Docker 的日志默认值只作用于新建容器。通过 HostConfig.LogConfig 判断旧容器是否缺少大小限制,在保留数据和日志后更新服务配置并重建。

daemon.json 已经配置了 max-size 和 max-file,Docker 服务也重新启动过,但原有容器的 JSON 日志仍越写越大。此时要看该容器保存的日志配置:Docker 守护进程的新默认值不会追溯修改已经创建的容器。

本文适用于 Docker Engine 的 json-file 日志驱动。示例部署命令使用 Compose V2,服务名 app、文件名 compose.yaml 和容器名 app-container 都需要替换成实际值。其他日志驱动的存储与轮转选项不能直接套用。

容器实际保存了哪些日志选项

只查看目标容器的日志配置,避免把整个容器环境和敏感参数一起输出:

docker inspect --format '{{json .HostConfig.LogConfig}}' app-container

若得到下面的结果,说明这个容器没有保存期望的大小与数量上限:

{"Type":"json-file","Config":{}}

json-file 的 max-size 默认不限大小。max-file 则需要配合 max-size 才有轮转保留数量的意义,只配置文件个数不能触发按大小轮转。

再看守护进程的默认驱动:

docker info --format '{{.LoggingDriver}}'

这里显示 json-file,只能说明默认驱动类型,不能证明目标容器使用了新 log-opts。容器在创建时保存日志驱动和选项;之后重启同一个容器,仍会沿用这份配置。

如果 LogConfig 已包含正确的 max-size、max-file,就不属于“旧容器没有继承新默认值”这一分支。继续确认占用空间的究竟是这个容器的 Docker 日志,还是应用自己写进卷里的文件,以及是否有大量其他容器各自保留日志。单容器轮转参数不是整台主机的磁盘配额。

把限制明确写进该服务的 Compose 配置

对于由 Compose 管理的服务,可以直接在现有服务下声明日志配置,避免依赖全局默认值。下面是要合并到现有 services.app 下的片段;保留原来的镜像、网络、端口和数据挂载:

services:
  app:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

这表示按 10m 的文件大小阈值轮转,并保留至多三个日志文件。值写成字符串,尤其不要把 max-file 写成没有引号的整数。具体阈值应由日志增长速度和需要保留的时间决定;超过保留数量后,较旧日志会被删除,需要长期留存的日志应先有独立采集或归档安排。

在原项目目录、沿用原项目名和配置文件组合检查配置。若部署原来使用多个 -f 文件或 -p 项目名,以下命令也要带上同一组选项:

docker compose -f compose.yaml config -q
docker compose -f compose.yaml ps -a -q app

第二条命令用于记录旧容器 ID;多副本服务会返回多个 ID,后续应逐一核对。不要换到另一个项目名下启动一套同名服务,误把新项目当成原服务的更新。

重建之前保留数据、日志和回退配置

修改文件还没有改变现有容器。应用这项配置需要创建替代容器,会短暂停止目标服务,也会丢失原容器可写层中没有单独持久化的内容。

先保留原 Compose 配置与可用镜像版本,确认业务数据挂载位置和可恢复备份,并按现有日志采集方式保存必须留存的旧日志。数据库等有一致性要求的数据应走自身备份流程,不能用“已经挂卷”代替备份。不要同时更新镜像版本,否则日志修复和应用升级的风险会混在一起。

准备完成后,在维护窗口只重建目标服务:

docker compose -f compose.yaml up -d --no-deps --force-recreate app

--no-deps 避免顺带启动依赖服务,--force-recreate 明确创建替代容器。不要为这项修改执行 down -v、删除数据卷或清理所有容器。Compose 重建会保留挂载的卷,但容器可写层中的临时修改不会随之保留。

核验新容器,而不是只看配置文件

再次取得该服务的容器 ID,再将其中一个 ID 填入检查命令:

docker compose -f compose.yaml ps -a -q app
docker inspect --format '{{json .HostConfig.LogConfig}}' NEW_CONTAINER_ID

新 ID 应与被替代的旧容器不同,日志配置应包含以下键值,JSON 中键的顺序不影响含义:

{"Type":"json-file","Config":{"max-size":"10m","max-file":"3"}}

接着确认业务健康检查正常,应用的标准输出和标准错误仍进入预期采集链路。通过正常业务日志和已有磁盘监控观察轮转;日志尚未到达阈值时,没有发生轮转并不能说明配置失败。不要为了尽快看到轮转,在生产服务里持续制造大量日志。

Docker 管理的 JSON 日志文件应由 Docker 自己维护。不要把它们交给另一套 logrotate,也不要直接删除或截断仍在写入的底层文件;这类外部操作可能干扰日志驱动。应用自行写在挂载目录里的日志则属于另一条管理路径,不受这里的限制控制。

如果需要撤回,恢复保存的服务配置和原镜像版本,再按相同维护流程重建。恢复配置不会找回已经被轮转删除的历史日志,也不会撤销应用已经写入的数据。