Docker 应用如何用 Filebeat + Logstash 收集日志?
Docker 应用日志收集方案:应用写 stdout → json-file 落盘 /var/lib/docker/containers → Filebeat 采集 → Logstash 清洗 → ES。本文给出挂载要点与 autodiscover 配置。
标准链路:容器日志写 stdout/stderr(Docker json-file 驱动落盘)→ Filebeat 挂宿主机的 /var/lib/docker/containers 目录采集 → 送 Logstash 解析 → 入 ES。容器内不要自己写日志文件。
关键配置
应用侧:日志输出到 stdout(12-Factor 原则),Docker 默认 json-file 驱动落盘。
Filebeat(宿主机或容器均可,普通 Docker 主机可直接运行;Kubernetes 可用 DaemonSet):
filebeat.autodiscover:
providers:
- type: docker
hints.enabled: true # 支持容器 labels 声明日志类型
hints.default_config:
type: filestream
id: container-${data.container.id}
paths:
- /var/lib/docker/containers/${data.container.id}/*.log
parsers:
- container:
stream: all
format: docker
processors:
- add_docker_metadata: ~ # 附加容器名/镜像/标签
output.logstash:
hosts: ["logstash:5044"]
这是 Docker json-file 的示例;路径取决于 Docker data-root 和日志驱动。Docker 将这些文件视作内部实现,生产采集方式需按驱动支持情况确认。
Logstash 侧:接收 Filebeat 已合并的事件后做 grok 解析。co.elastic.logs/multiline.* 是由 Filebeat hints 读取的配置,不会自动成为 Logstash 多行规则。
注意事项
- 挂载只读:
-v /var/lib/docker/containers:/var/lib/docker/containers:ro,docker.sock 可供元数据查询,但访问它具有高权限,挂载为只读不等于 Docker API 只读; - json-file 驱动要配轮转:
--log-opt max-size=10m --log-opt max-file=3; - K8s 通常使用 CRI 格式和 /var/log/containers 符号链接,需挂载链接目标并使用对应解析器;不能照搬 Docker json-file 假设。
常见问题(FAQ)
Q:应用已经写日志文件了怎么办? 挂卷到宿主机,Filebeat 按文件路径采集。
Q:多行堆栈怎么处理? 应在 Filebeat 输入端按容器日志流完成 multiline,再发送 Logstash;Beats input 不支持 multiline codec,混合来源后合并也会串日志。