第2章:Docker日志驱动与配置
日志驱动这东西,说白了就是Docker把容器里的日志吐到哪去的问题。我刚开始用Docker那会儿,觉得默认的json-file就挺好,直到有一次线上容器把磁盘撑爆了...嗯,从那以后我再也不敢忽视日志驱动和轮转配置了。
2.1 日志驱动概览
Docker支持多种日志驱动,每种都有它的适用场景。我个人习惯把日志驱动分成两类:本地存储型和远程转发型。
| 驱动名称 | 类型 | 适用场景 |
|---|---|---|
| json-file | 本地存储 | 单机调试、小规模部署 |
| journald | 本地存储 | 与systemd集成紧密的环境 |
| syslog | 远程转发 | 已有syslog基础设施的团队 |
| fluentd | 远程转发 | 云原生日志管道、统一收集 |
| gelf | 远程转发 | Graylog用户 |
| awslogs | 云服务 | AWS CloudWatch用户 |
2.2 json-file驱动详解
这是Docker的默认驱动。容器内进程往stdout/stderr写的内容,都会被Docker捕获并写入宿主机上的JSON文件。每个容器对应一个文件,路径通常是:
/var/lib/docker/containers/<container_id>/<container_id>-json.log
文件内容长这样:
{"log":"2024-01-15 10:30:22 INFO UserService - 用户登录成功\n","stream":"stdout","time":"2024-01-15T10:30:22.123456789Z"}
{"log":"2024-01-15 10:30:23 ERROR OrderService - 订单超时\n","stream":"stderr","time":"2024-01-15T10:30:23.987654321Z"}
每条日志都是独立的JSON对象。好处是结构清晰,坏处是...文件会无限增长。我在项目中遇到过,一个高并发的Java应用,一天能写20GB日志文件,直接把磁盘打满。
2.3 配置日志轮转与大小限制
这才是本章的重点。配置日志轮转有两种方式:全局配置和容器级配置。
2.3.1 全局配置(daemon.json)
修改 /etc/docker/daemon.json,然后重启Docker守护进程:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3",
"compress": "true"
}
}
参数说明:
- max-size:单个日志文件的最大大小。超过这个值就轮转。单位可以是k、m、g。
- max-file:保留的日志文件个数。轮转后旧文件会被重命名或删除。
- compress:是否压缩旧日志文件。压缩后是.gz格式,能省不少空间。
举个例子,上面配置的效果是:每个容器最多保留3个日志文件,每个文件不超过10MB,旧文件自动压缩。这样最多占用约30MB磁盘空间。
2.3.2 容器级配置
启动容器时指定:
docker run -d \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
--log-opt compress=true \
nginx:latest
或者在docker-compose.yml里配置:
version: '3.8'
services:
web:
image: nginx:latest
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
compress: "true"
2.4 journald驱动
journald是systemd的日志系统。如果你用systemd管理服务,journald驱动可以让你用journalctl统一查看所有日志。
{
"log-driver": "journald",
"log-opts": {
"tag": "{{.Name}}/{{.ID}}"
}
}
查看容器日志:
journalctl -u docker.service --since "5 min ago"
journalctl CONTAINER_NAME=nginx
journald的好处是自带日志轮转和压缩,不需要额外配置。但坏处是...日志格式是二进制的,不能直接用cat或tail查看。而且journald默认日志大小限制是系统磁盘的10%,对于日志量大的场景可能不够。
/etc/systemd/journald.conf配置。关键参数是SystemMaxUse,我一般设为1G。
2.5 syslog驱动
syslog驱动把日志转发到本机或远程的syslog服务。适合已经有ELK或Graylog等syslog接收端的团队。
docker run -d \
--log-driver syslog \
--log-opt syslog-address=tcp://192.168.1.100:514 \
--log-opt syslog-facility=daemon \
--log-opt tag="{{.Name}}" \
nginx:latest
参数说明:
- syslog-address:syslog服务器地址。支持tcp、udp、unix socket。
- syslog-facility:syslog设施类型,默认是daemon。
- tag:日志标签,方便区分不同容器。
syslog的优点是标准化,很多运维工具都支持。但缺点也很明显:UDP传输可能丢日志,TCP传输有连接开销。我一般只在已有syslog基础设施时才用这个驱动。
2.6 fluentd驱动
这是云原生场景下我最推荐的驱动。fluentd驱动把日志直接发给fluentd或fluentbit,然后由它们做进一步处理。
{
"log-driver": "fluentd",
"log-opts": {
"fluentd-address": "localhost:24224",
"tag": "docker.{{.Name}}",
"fluentd-async-connect": "true"
}
}
fluentd驱动的优势:
- 支持异步连接,不会因为fluentd挂了就影响容器运行
- 日志格式灵活,可以加自定义字段
- 与Kubernetes集成良好,很多K8s集群都用这个方案
2.7 日志驱动选择建议
说了这么多,到底该选哪个?我总结了一个简单的决策树:
- 单机调试:json-file + 轮转配置,简单够用
- systemd环境:journald,统一管理
- 已有syslog:syslog驱动,无缝集成
- 云原生/K8s:fluentd/fluentbit,灵活强大
- AWS用户:awslogs,直接送CloudWatch
下一章我们会聊聊日志采集的架构设计,包括sidecar模式、daemonset模式这些实战内容。到时候见。