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 驱动是单机推荐:默认 json-file 的升级版——压缩、轮转、性能更好。
- 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 压缩文件),零分配设计性能更好——它是大多数单机场景的最优默认。
2. 全局配置:daemon.json
{
"log-driver": "local",
"log-opts": {
"max-size": "20m",
"max-file": "5",
"compress": "true"
}
}
改完 systemctl restart docker 生效(作用于新建容器)。单容器覆盖:
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,容器内时区与宿主机一致(挂载 /etc/localtime 或设 TZ);
- 别在容器里跑日志轮转:轮转由驱动层(local/json-file 的 log-opts)或平台层负责。
4. 多主机集中化
单机 docker logs 够用,多主机、多容器时代必须集中化:
- 采集:观测云 DataKit 以容器方式部署(挂载 /var/run/docker.sock 或 /var/lib/docker/containers),自动发现并采集所有容器日志,按容器名/镜像/标签打标
service; - 解析:单行 JSON 自动解析为字段;Pipeline 映射标准
status/time;按 compose project、K8s 命名空间等元数据分组; - 检索告警:日志查看器跨主机检索;监控器对 error 日志、特定关键字(OOM、panic)告警,通知钉钉/企业微信/飞书;
- 治理:多索引按服务拆保留策略,历史数据归档对象存储。
相比"fluentd 驱动直推后端"的模式,DataKit 本地采集 + 转发的架构更可靠:网络抖动时本地缓冲,后端不可达不影响容器运行。
常见问题(FAQ)
容器里写日志文件会有什么问题?
容器删除文件即失;写容器层(可写层)性能差且撑爆磁盘配额;挂卷写文件则需要自己管轮转与多机汇聚。除非有特殊合规要求,否则一律 stdout。
docker logs 看不到日志了?
两种常见原因:容器用了非 json-file/local 的驱动(docker logs 只支持这两种 + journald 部分支持);或应用把日志写进了容器内文件而非 stdout。docker inspect 确认驱动。
多行堆栈日志被拆散怎么解决?
根治:应用输出单行 JSON(堆栈作为字段值)。临时方案:采集侧 DataKit 支持多行合并规则(按行首时间戳等模式把多行拼回一条)。
local 驱动的日志能用 docker logs 看吗?
能。local 驱动完全兼容 docker logs 命令,同时文件体积更小(压缩),是 json-file 的无痛升级。
系列阅读
- 上一篇:MongoDB 日志详解
- 下一篇:docker logs 命令详解
- 相关阅读:Docker Compose 日志指南 | 什么是日志聚合