使用 Loki + Promtail + Grafana 实现 Docker 容器日志采集与可视化
本文将带你从零搭建 Loki 日志系统,通过 Promtail 采集 Docker 容器日志,并使用 Grafana 进行可视化展示与搜索。
一、前言
在微服务架构中,日志是定位问题的关键。传统的 ELK(Elasticsearch + Logstash + Kibana)方案功能强大,但资源消耗高、配置复杂。
Grafana Labs 推出的 Loki 是一个轻量级、成本低的日志系统,灵感来自 Prometheus,天然支持容器化和云原生场景。
本篇将带你实现:
- ✅ 自动采集所有 Docker 容器日志
- ✅ 使用 Grafana 可视化日志
- ✅ 支持多容器筛选与关键字搜索
- ✅ 可拓展日志告警与监控体系
二、系统架构
整体架构如下:
- Promtail:采集容器日志并推送给 Loki
- Loki:存储和索引日志数据
- Grafana:展示与分析日志
三、环境准备
本文基于 Docker Compose 部署,环境如下:
项目 | 版本 |
---|---|
操作系统 | Ubuntu / Windows / macOS |
Docker | ≥ 24.0 |
Grafana | latest |
Loki | 2.9.0 |
Promtail | 2.9.0 |
/docker-logging
├── grafana/
├── loki/
│ └── loki-config.yml
├── promtail/
│ └── promtail-config.yml
└── docker-compose.yml
docker-compose.yml
version: '3.8'networks:my-network: # 复用你已有的 redis 网络external: trueservices:redis-exporter:image: oliver006/redis_exporter:latestcontainer_name: redis-exporterrestart: unless-stoppednetworks:- my-networkports:- "9121:9121" # Redis Exporter 端口environment:REDIS_ADDR: "redis://redis:6379" # 改成你的 redis 容器名或服务名REDIS_PASSWORD: "Wktc22]s"depends_on:- redisloki:image: grafana/loki:2.9.0container_name: lokinetworks:- my-networkports:- "3100:3100"command: -config.file=/etc/loki/local-config.yamlpromtail:image: grafana/promtail:2.9.0container_name: promtailnetworks:- my-networkvolumes:- /var/lib/docker/containers:/var/lib/docker/containers:ro- /var/run/docker.sock:/var/run/docker.sock- /root/monitoring-project/promtail-config.yml:/etc/promtail/config.yml:rodepends_on:- lokiprometheus:image: prom/prometheus:latestcontainer_name: prometheusrestart: unless-stoppednetworks:- my-networkports:- "9099:9099"volumes:- /root/monitoring-project/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml- /root/monitoring-project/prometheus/data:/prometheuscommand:- "--config.file=/etc/prometheus/prometheus.yml"- "--storage.tsdb.path=/prometheus"- "--web.listen-address=:9099"grafana:image: grafana/grafana:latestcontainer_name: grafanarestart: unless-stoppednetworks:- my-networkports:- "3000:3000"volumes:- /root/monitoring-project/grafana/provisioning:/etc/grafana/provisioning- /root/monitoring-project/grafana/data:/var/lib/grafanaredis:image: redis:7.2.4container_name: redisrestart: unless-stoppednetworks:- my-networkports:- "6379:6379"volumes:- /mydata/redis/data:/data- /root/monitoring-project/redis/redis.conf:/usr/local/etc/redis/redis.confcommand: ["redis-server", "/usr/local/etc/redis/redis.conf"]deploy:resources:limits:memory: 1g
promtail-config.yml
server:http_listen_port: 0grpc_listen_port: 0positions:filename: /tmp/positions.yamlclients:- url: http://loki:3100/loki/api/v1/pushscrape_configs:- job_name: docker-logsdocker_sd_configs:- host: unix:///var/run/docker.sockrefresh_interval: 10srelabel_configs:# 只抓 Redis 容器# - source_labels: [__meta_docker_container_name]# regex: '.*redis.*'# action: keep# 给每条日志加 container 标签- source_labels: [__meta_docker_container_name]regex: '(?:/)?(.*)'target_label: container# 添加 job 标签- target_label: jobreplacement: docker-logs
未完待续… 敬请期待