容器日志需同时实现集中采集与宿主机持久化:一路通过Docker json-file驱动自动写入/var/lib/docker/containers/下的JSON文件并配置max-size/max-file轮转;另一路用Filebeat/Fluent Bit双写,既发远端又落盘本地,且须挂载日志目录为只读。

容器日志要既“重定向进集中系统”,又“持久化保存到宿主机”,关键不是在容器里写文件,而是分两路处理:一路让 stdout/stderr 被 Docker 日志驱动或采集器捕获并转发;另一路通过配置确保原始日志文件(JSON 格式)在宿主机上安全落盘、自动轮转、不占满磁盘。
用 Docker 原生日志驱动 + 本地落盘双写
Docker 默认的 json-file 驱动本身就会把 stdout/stderr 写入宿主机文件(路径:/var/lib/docker/containers/<id>/<id>-json.log),你只需合理配置轮转策略,就能实现本地持久化:
- 启动容器时加日志限制参数,防止单个日志文件无限增长:
--log-opt max-size=20m --log-opt max-file=5
表示单个日志文件最大 20MB,最多保留 5 个历史文件 - 日志文件默认权限为 644,宿主机 root 或 docker 组用户可读;如需其他用户访问,可在挂载日志目录后调整权限或使用
log-opt tag添加标识便于识别 - 该方式无需改应用代码,也不依赖外部采集器,适合开发、测试或审计留痕等需要本地存档的场景
用 Filebeat / Fluent Bit 主动采集并同步落盘
当已有日志采集链路(如对接 ELK 或 Loki),又要求宿主机有完整副本时,可让 Filebeat 或 Fluent Bit 同时完成两件事:读取 JSON 日志文件 + 双写输出(一份发远端,一份存本地):
- Filebeat 配置中启用
container输入类型,并设置paths指向 Docker 日志目录:paths: ["/var/lib/docker/containers/*/*.log"] - 在 output 部分配置两个目标:一个
elasticsearch或logstash,另一个用file输出插件写入自定义路径(如/var/log/myapp/),并开启rotate_every_kb和number_of_files控制本地落盘行为 - 注意:采集容器必须挂载宿主机日志目录,且设为只读:
-v /var/lib/docker/containers:/var/lib/docker/containers:ro
避免日志“消失”的常见错误
很多团队以为加了重定向就等于持久化,结果发现 docker logs 查不到、采集器收不到、宿主机也找不到日志——问题往往出在应用层主动绕开了 Docker 的日志通路:
- ❌ 错误写法(日志脱离 Docker 管控):
CMD ["sh", "-c", "python app.py > /var/log/app.log 2>&1"]
此时所有输出都进了容器内文件,Docker 完全感知不到 - ✅ 正确做法(保持 stdout/stderr 通畅):
应用直接 print/console.log;或用软链接把服务日志指向标准输出,例如:ln -sf /dev/stdout /var/log/nginx/access.logln -sf /dev/stderr /var/log/nginx/error.log - 若业务强依赖容器内日志文件(如某些 Java 应用),可配合
tail -f方式让采集器监听该文件,但务必同时挂载该路径到宿主机(-v /host/logs:/app/logs),才能实现真正持久化
合规场景下的本地+远程双写方案
部分行业(如金融、政务)明确要求日志必须“本地留存至少 180 天 + 实时上传至审计平台”。此时推荐组合使用:
- Docker 启动参数指定
--log-driver=json-file并配好轮转(保障本地可查) - 另起一个 Fluent Bit 容器,挂载
/var/lib/docker/containers,用tail插件读取 JSON 日志,经filter解析后,用两个output分别发往远程日志平台和本地 NFS/S3FS 挂载点 - 宿主机上对
/var/lib/docker/containers做定期快照(如用rsync + cron)或启用logrotate配合压缩归档,满足离线审计要求


















