Docker API 网关日志占满磁盘?检查 json-file 轮转与容器实际配置
区分容器输出、应用文件与数据库增长,检查 json-file 的 max-size 和 max-file,说明为什么旧容器不继承新配置,并附安全重建流程与离线检查示例。
自建 API 网关突然写入失败、日志中出现 no space left on device,不一定是模型服务出了问题。先确认哪块磁盘、哪类数据在增长;如果是 Docker 收集的容器输出,给应用设置“日志保留 7 天”也未必能限制它。
本文面向 Docker Engine 与 Compose 部署,处理容器输出日志的容量与轮转。它不替代数据库清理或备份方案,也不适用于所有托管平台。示例经过离线配置检查,没有执行真实 Docker 轮转或付费 API 请求。
1. 先区分容器输出、应用文件和业务数据
Docker 的 json-file 驱动收集容器标准输出、标准错误,为日志行附加时间和来源;每个容器有自己的日志文件。[1] 应用直接写入挂载目录的文件、数据库中的调用记录,不会因为设置这个驱动的轮转参数就自动清理。
| 增长的对象 | 从哪里确认 | 由谁限制 |
|---|---|---|
| 容器 stdout/stderr | 目标容器的日志驱动、日志增长监控 | Docker 日志驱动及应用输出量 |
| 应用自己写的文件 | 应用日志配置与实际挂载位置 | 应用或其配套轮转机制 |
| 账户、余额、请求明细数据库 | 数据库位置、表与索引增长 | 数据库和应用的数据保留策略 |
| 镜像、构建缓存及其他文件 | Docker 对象清单、宿主机磁盘监控 | 对应对象的生命周期管理 |
记录同一时间点的可用空间、增长速度、报错服务和实际挂载关系。Linux 上还要检查 inode 是否耗尽;Docker Desktop 要区分宿主机空间和其 Linux 虚拟机的存储。不要仅凭目录名称把数据库卷认成“可删缓存”。
空间已紧张时,先限制非必要的高频调试输出和新负载,保留脱敏故障摘要;不要把全量日志再导出到同一块快满的盘。如果业务写入已失败,应按维护流程限制入口并检查结算状态,不能只清出一点空间就宣布恢复。涉及数据保护时先看网关备份与恢复演练。
2. 看目标容器的配置,别只看全局默认值
Docker 文档说明 json-file 默认不做轮转,max-size 默认值为 -1,表示不设大小上限;max-file 只有同时设置 max-size 才有效。[1][2] 但你的运行环境可能已经改过默认驱动,所以要实际读取。
以下为只读命令。先确认 Docker CLI 连接的是目标部署环境,将 gateway-container 换成已经核对的容器名或 ID;它是示例占位名称。不要把整份 docker inspect 输出发到工单,因为其他字段可能含环境变量和凭据。
docker info --format '{{.LoggingDriver}}'
docker inspect --type container --format '{{json .HostConfig.LogConfig}}' gateway-container
第一行是守护进程默认驱动,第二行才是指定容器创建时采用的日志配置。[2][4] 默认值已是新值,不证明旧容器也更新了。对每个网关副本、反向代理和后台任务分别检查,不能只检查一个实例。
如果看到 json-file 且没有大小上限,重点排查未轮转的输出;若是 local、journald 或远端驱动,应转向对应驱动的规则,不能照搬 json-file 的结论。Docker 推荐在适用场景使用默认会轮转的 local 驱动,但切换前必须确认现有采集器是否依赖 JSON 文件格式。[2][3]
3. 为现有 Compose 服务补上明确的轮转配置
下面只是合并进现有 Compose 文件的片段,不是完整部署文件。gateway 要换成真实服务名;保留原来的镜像、挂载、网络和其他设置,不用这个片段覆盖原文件。[5]
services:
gateway:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
含义是日志达到大小阈值时轮转,最多保留 3 个日志文件,超出数量时移除最旧文件。[1] 这里的数值用于说明配置,不是所有网关的推荐容量。选值时应考虑单容器输出速率、实例数量、故障排查窗口和可用空间;大小轮转不能保证保留固定天数。
例如持续高频报错可能很快覆盖旧日志,即使容器一直正常运行,也不代表还能找到昨天的记录。多个副本各有自己的限额;阈值乘文件数也不是整台主机的磁盘硬配额,不能忘记数据库、其他日志、元数据和临时空间。需要保留的计费、审计证据应有独立的存储和访问策略,见日志保留时间与最小字段。
如果采用全局 daemon.json 配置,Docker 文档要求 log-opts 的值写成字符串;重启守护进程后也只影响随后创建的容器。[1][2] 全局调整会涉及其他服务,不能把它当成只修改当前网关的小操作。
4. 应用配置时要重建,并保护持久化数据
日志配置在创建容器时确定。只修改文件或重启现有容器,不会让旧容器自动继承新的日志参数。[2] Compose 的 up 会根据配置或镜像变化重建服务容器并保留挂载卷;--no-recreate 会阻止重建。[6]
正式应用前,先保存旧配置,确认数据库和上传文件确实位于已核对的持久化存储中,完成可恢复备份,固定镜像版本并安排中断窗口。等待在途请求和账务处理收敛后,按既有部署流程重建目标服务;不要为了日志变更同时升级网关或删除卷。容器可写层里的数据不能当成已被保留。
重建后再次读取每个新容器的 HostConfig.LogConfig,记录容器 ID 与创建时间,确认驱动、max-size 和 max-file 符合预期。文件正确但运行实例仍旧,是部署未生效,不是继续调小数值能解决的问题。配置链路可参考Compose 修改后不生效的排查。
轮转配置主要限制后续增长,不是通用的历史空间回收命令。Docker 明确警告不要用外部工具直接操作驱动管理的日志文件,否则可能干扰日志系统。[1][3] 不手工删除或截断这些文件,也不把批量清理容器、镜像或卷作为默认修复。旧容器是否可移除、日志是否需留证,应在确认业务数据位置后按维护流程逐项处理。
5. 用离线检查器先拦住明显漏项
下面的 Node.js 示例只检查手工复制的日志配置对象,不连接 Docker、不读取密钥,也不触发重建。它按本教程的审查规则要求显式配置两个限额;Docker 允许的其他格式仍需查官方文档,返回 review-* 不等于 Docker 一定拒绝该配置。
function reviewRotation(config) {
const isObject = value => value !== null &&
typeof value === 'object' && !Array.isArray(value)
if (!isObject(config) || typeof config.Type !== 'string' ||
!config.Type.trim()) return 'invalid-input'
if (config.Type !== 'json-file') return 'other-driver'
const options = config.Config
if (!isObject(options)) return 'review-options'
const size = options['max-size']
if (typeof size !== 'string' || !/^[1-9]\d*[kmg]$/i.test(size)) {
return 'review-size'
}
const sizeValue = Number(size.slice(0, -1))
if (!Number.isSafeInteger(sizeValue)) return 'review-size'
const count = options['max-file']
if (typeof count !== 'string' || !/^[1-9]\d*$/.test(count) ||
!Number.isSafeInteger(Number(count))) return 'review-count'
return 'rotation-configured'
}
console.log(reviewRotation({
Type: 'json-file',
Config: { 'max-size': '10m', 'max-file': '3' }
}))
正常样例输出 rotation-configured,只代表字段通过这项离线检查。缺少 max-size、填 -1、只有 max-file 都会得到 review-size;显式文件数缺失则返回 review-count,尽管 Docker 对 max-file 有默认值 1。[1] 其他驱动得到 other-driver,不能据此判为无限增长。
本地验证覆盖了正常配置、空对象、错误类型、缺少限额、非正数和超大整数。它没有模拟 Docker 写盘,不证明配置已经部署、日志实际轮转或保留时间满足要求。
6. 最后验收增长、可查询性和业务状态
在隔离测试环境,用有限数量、固定长度、不含秘密的合成日志验证轮转;不要让测试容器挂载生产卷或访问付费上游。设置测试输出上限和停止条件,观察旧记录覆盖与新记录可查询性,再决定生产参数。本文没有在真实 Docker 上执行这一演练。
| 验收现象 | 下一步判断 |
|---|---|
| 新容器参数正确,磁盘仍持续增长 | 查应用文件、数据库、其他容器以及集中日志存储 |
| 日志很快查不到早期记录 | 根据增长率重估容量,检查外部留存与采集完整性 |
| 只有部分副本限额正确 | 查部署目标、覆盖文件和遗漏的旧实例 |
| 网关仍有写入或结算错误 | 继续检查业务恢复,不能用磁盘空闲代替账务验收 |
不要把 non-blocking 当成磁盘轮转的替代品:它改变日志传递模式,缓冲满时会丢弃新日志;它不自动保证所需证据完整。[2] 如果选用该模式,要明确能否接受丢日志,并验证采集告警。
最终保留一份记录:目标环境、容器身份、驱动与限额、变更时间、空间和增长率、可查询窗口、业务验证结果、尚未验证的范围。回滚配置后也要按同样流程重建并检查;被轮转移除的历史记录不会因为改回配置而恢复。
7. 官方资料与核对日期
资料核对日期:2026-10-30。以下为 Docker 官方文档;部分内容读取了其官方仓库中的 Markdown。实际部署以安装版本和环境为准。
- JSON File logging driver:默认上限、轮转参数、旧日志移除和文件访问边界。
- Configure logging drivers:默认驱动、单容器检查、创建时生效及阻塞/非阻塞模式。
- Local file logging driver:默认轮转、压缩及文件格式边界。
- docker inspect:按对象类型和模板读取配置。
- Compose services:logging:服务级驱动和选项。
- docker compose up:配置变更、容器重建与挂载卷。