Docker 日志策略与最佳实践:驱动选型、轮转配置与集中化
Docker 日志中文实战:logging driver 详解(json-file/local/syslog/journald/fluentd)、local 驱动的压缩轮转、daemon.json 全局配置与 per-container 覆盖、多行日志问题、应用写 stdout 的最佳实践,以及观测云 DataKit 集中采集落地方案。
容器日志与传统主机日志的最大区别:容器的可写层随容器删除而消失——停止或重启会保留它,挂载卷另有生命周期。Docker 的日志驱动(logging driver)体系正是为此而生:把容器 stdout/stderr 流接管到可靠的存储或转发渠道。本文讲清驱动选型、轮转配置与集中化最佳实践。
核心要点速览
- 应用只写 stdout/stderr 是容器日志第一原则:让 Docker 接管日志流,应用不碰文件。
- local 驱动是单机推荐:自带压缩与轮转,但内部格式不同,切换前需验证采集兼容性。
- daemon.json 全局配置 + 单容器 --log-driver 覆盖:统一基线、个别定制。
- 多主机集中化靠采集层:观测云 DataKit 采集容器日志,检索告警一站式。
1. 日志驱动全景
Docker 从容器进程的 stdout/stderr 捕获输出,交给 logging driver 处理:
docker info --format '{{.LoggingDriver}}' # 查看守护进程默认驱动
docker inspect -f '{{.HostConfig.LogConfig.Type}}' <容器> # 查看某容器的驱动
docker inspect -f '{{.LogPath}}' <容器> # 查看日志文件位置
# 默认 json-file 的日志在 /var/lib/docker/containers/<id>/<id>-json.log
| 驱动 | 行为 | 适用 |
|---|---|---|
| json-file | JSON 行写宿主机文件(默认) | 兼容性兜底 |
| local | 高性能本地存储,默认压缩轮转 | 单机推荐 |
| syslog / journald | 进系统日志体系 | 与传统运维整合 |
| fluentd / gelf / splunk | 直推日志服务 | 特定后端 |
| none | 丢弃 | 日志由应用自行外送 |
local 驱动优势:默认开启轮转,每容器按未压缩内容计约 100MB(5 个 20MB 文件),默认压缩轮转文件;这是 Docker 推荐的通用本地选项,实际性能和采集兼容性需验证。
2. 全局配置:daemon.json
{
"log-driver": "local",
"log-opts": {
"max-size": "20m",
"max-file": "5",
"compress": "true"
}
}
改完 systemctl restart docker 生效(作用于新建容器;旧容器必须重新创建,单纯 restart 不会采用新驱动)。单容器覆盖:
docker run --log-driver syslog --log-opt syslog-address=tcp://192.168.1.10:514 -d <镜像>
json-file 不配置 max-size 是磁盘事故的头号来源——一个高频日志容器就能把宿主机磁盘写满。任何驱动都要确认轮转参数就位。
3. 应用侧最佳实践
- 只写 stdout/stderr:Node 的 console、Python logging StreamHandler(stdout)、Java ConsoleAppender——别在容器里写本地文件;
- 单行日志:Docker 按行切分日志,Java 堆栈这类多行日志会被拆成多条孤立记录——输出单行 JSON 是减少多行拼接问题的推荐方式(堆栈作为 JSON 字段而非多行文本);
- 时间戳带时区:ISO-8601,统一使用 UTC 或保留明确偏移即可,不要求容器与宿主机时区相同;
- 别在容器里跑日志轮转:轮转由驱动层(local/json-file 的 log-opts)或平台层负责。
4. 多主机集中化
单机 docker logs 够用,多主机、多容器时代必须集中化:
- 采集:观测云 DataKit 以容器方式部署(挂载 /var/run/docker.sock 或 /var/lib/docker/containers),按启用的容器采集配置、权限和驱动支持范围发现并采集日志,再配置容器元数据与
service; - 解析:通过采集与 Pipeline 配置把单行 JSON 解析为字段;Pipeline 映射标准
status/time;按 compose project、K8s 命名空间等元数据分组; - 检索告警:日志查看器跨主机检索;监控器对 error 日志、特定关键字(OOM、panic)告警,通知钉钉/企业微信/飞书;
- 治理:多索引按服务拆保留策略,历史数据归档对象存储。
相比"fluentd 驱动直推后端"的模式,DataKit 本地采集 + 转发可提供缓冲,但容量、持久化和重试配置决定故障下的行为;需要实测网络中断、缓冲耗尽和恢复。Docker 的阻塞模式可能阻塞应用,非阻塞模式缓冲满时会丢日志。
常见问题(FAQ)
容器里写日志文件会有什么问题?
容器删除会丢失可写层中的文件,挂载卷内的文件不由这一规则决定;写容器层(可写层)性能差且撑爆磁盘配额;挂卷写文件则需要自己管轮转与多机汇聚。除非有特殊合规要求,否则一律 stdout。
docker logs 看不到日志了?
两种常见原因:驱动不支持读取,或远程驱动的 dual logging 本地缓存被关闭/不可用(json-file、local、journald 支持读取,部分远程驱动可通过 dual logging 支持 docker logs);或应用把日志写进了容器内文件而非 stdout。docker inspect 确认驱动。
多行堆栈日志被拆散怎么解决?
根治:应用输出单行 JSON(堆栈作为字段值)。临时方案:采集侧 DataKit 支持多行合并规则(按行首时间戳等模式把多行拼回一条)。
local 驱动的日志能用 docker logs 看吗?
能。local 驱动完全兼容 docker logs 命令,同时文件体积更小(压缩),但文件是 Docker 内部格式,直接读取 json-file 的采集器不能因此无修改切换。
系列阅读
- 上一篇:MongoDB 日志详解
- 下一篇:docker logs 命令详解
- 相关阅读:Docker Compose 日志指南 | 什么是日志聚合
[1]: 观测云文档《DataKit 日志采集综述》https://docs.guance.com/integrations/datakit-logging/
[2]: 观测云文档《日志查看器》https://docs.guance.com/logs/explorer/
[3]: 观测云文档《监控》https://docs.guance.com/monitoring/