3. Loki 快速部署:Docker Compose 方式搭建 Loki + Promtail + Grafana 本地环境
在 CI/CD 流水线 SLI 监控体系中,日志是还原故障现场、计算错误率与延迟分布的关键数据源。本章将使用 Docker Compose 在本地一键搭建 Loki + Promtail + Grafana 三件套,为后续的 SLI 口径采集与日志监控实战提供可复现的实验环境。
环境目标:单机部署,日志采集 → 存储 → 可视化链路完整,支持 LogQL 查询与 SLI 看板构建。
3.1 组件角色与数据流
Loki 采用 「推送-存储-查询」 的轻量架构,与 Prometheus 的指标监控体系高度互补。三个核心组件的职责如下:
| 组件 | 角色 | 关键端口 | 数据方向 |
|---|---|---|---|
| Promtail | 日志采集 Agent | 9080 (HTTP) | 读取本地日志文件 → 推送至 Loki |
| Loki | 日志存储与查询引擎 | 3100 (HTTP/gRPC) | 接收日志 → 索引 + 存储 → 响应 LogQL 查询 |
| Grafana | 可视化与告警面板 | 3000 (HTTP) | 从 Loki 查询日志 → 展示图表/表格/告警 |
下图展示了日志从产生到可视化的完整数据流:
架构要点:Promtail 是「有状态」的日志采集器,它会记录日志文件的读取偏移量,避免重复推送或丢失日志。Loki 本身不解析日志内容,只按标签(Label)索引,因此查询性能远高于 Elasticsearch 等全文索引方案。
3.2 环境准备与目录结构
在开始部署前,请确保宿主机已安装 Docker Engine 20.10+ 和 Docker Compose v2+。建议在 Linux 或 macOS 环境下操作,Windows 用户可使用 WSL2。
创建项目目录并规划文件结构:
mkdir -p ~/loki-lab/{config,data/loki,data/grafana,logs}
cd ~/loki-lab
| 目录/文件 | 用途 |
|---|---|
docker-compose.yml |
定义 Loki、Promtail、Grafana 三个服务 |
config/loki-config.yml |
Loki 配置文件(存储、认证、限制) |
config/promtail-config.yml |
Promtail 配置文件(采集目标、标签、推送地址) |
data/loki/ |
Loki 数据持久化目录(boltdb-shipper + 对象存储) |
data/grafana/ |
Grafana 数据持久化目录(配置、插件、看板) |
logs/ |
模拟 CI/CD 流水线日志的样本目录 |
3.3 编写配置文件
3.3.1 Loki 配置(config/loki-config.yml)
Loki 采用 boltdb-shipper 模式,将索引和数据统一存储在本地文件系统,适合单机开发与测试:
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9095
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2024-01-01
store: boltdb-shipper
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
ingestion_rate_mb: 10
ingestion_burst_size_mb: 20
生产环境注意:上述配置关闭了认证(auth_enabled: false)且使用单副本,仅适用于本地实验。生产环境必须启用认证、多副本及对象存储(如 S3/GCS)。
3.3.2 Promtail 配置(config/promtail-config.yml)
Promtail 需要明确指定日志采集源、标签以及 Loki 的推送地址:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: cicd-pipeline-logs
static_configs:
- targets: [localhost]
labels:
job: cicd-pipeline
__path__: /var/log/cicd/*.log
pipeline_stages:
- regex:
expression: '^(?P<level>\w+)\s+(?P<timestamp>\S+)\s+(?P<message>.*)$'
- labels:
level:
- timestamp:
source: timestamp
format: RFC3339
标签设计:
job 标签用于区分不同的流水线阶段(build/test/deploy),level 标签用于快速过滤 ERROR/WARN/INFO 级别日志。合理的标签基数(cardinality)是 Loki 性能的关键。
3.3.3 Docker Compose 编排(docker-compose.yml)
将三个服务整合到同一个网络内,并挂载配置与数据目录:
version: "3.8"
networks:
loki-net:
driver: bridge
services:
loki:
image: grafana/loki:2.9.2
container_name: loki
ports:
- "3100:3100"
- "9095:9095"
volumes:
- ./config/loki-config.yml:/etc/loki/loki-config.yml
- ./data/loki:/loki
command: -config.file=/etc/loki/loki-config.yml
networks:
- loki-net
restart: unless-stopped
promtail:
image: grafana/promtail:2.9.2
container_name: promtail
volumes:
- ./config/promtail-config.yml:/etc/promtail/promtail-config.yml
- ./logs:/var/log/cicd
- /var/log:/var/log
command: -config.file=/etc/promtail/promtail-config.yml
networks:
- loki-net
restart: unless-stopped
depends_on:
- loki
grafana:
image: grafana/grafana:10.2.3
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- ./data/grafana:/var/lib/grafana
networks:
- loki-net
restart: unless-stopped
depends_on:
- loki
3.4 启动与验证
执行以下命令启动所有服务:
cd ~/loki-lab
docker compose up -d
等待 10~15 秒后,使用 docker compose ps 检查三个容器的状态,应全部显示 Up:
NAME IMAGE STATUS PORTS
loki grafana/loki:2.9.2 Up 0.0.0.0:3100->3100/tcp
promtail grafana/promtail:2.9.2 Up 0.0.0.0:9080->9080/tcp
grafana grafana/grafana:10.2.3 Up 0.0.0.0:3000->3000/tcp
生成模拟日志以验证数据流:
# 生成 CI/CD 流水线模拟日志
for i in {1..5}; do
echo "INFO 2025-01-15T10:00:0${i}Z Build stage completed for commit a1b2c3d${i}" >> ~/loki-lab/logs/pipeline.log
echo "WARN 2025-01-15T10:00:1${i}Z Test flaky detected in module auth" >> ~/loki-lab/logs/pipeline.log
echo "ERROR 2025-01-15T10:00:2${i}Z Deploy failed: connection timeout" >> ~/loki-lab/logs/pipeline.log
done
3.5 配置 Grafana 数据源与快速查询
打开浏览器访问 http://localhost:3000,使用 admin / admin 登录。按以下步骤添加 Loki 数据源:
- 进入 Configuration → Data Sources → Add data source。
- 选择 Loki,在 URL 字段填入
http://loki:3100。 - 点击 Save & Test,确认返回绿色提示
Data source connected and labels found.
切换到 Explore 页面,输入以下 LogQL 查询验证日志采集:
{job="cicd-pipeline"} |= `ERROR`
预期结果:返回 5 条包含 ERROR 的模拟日志,每条日志携带 job、level 等标签。
验证清单:
- ✅ Loki 3100 端口可访问,
/ready返回 200 - ✅ Promtail 9080 端口可访问,
/targets显示采集文件列表 - ✅ Grafana 3000 端口可访问,Loki 数据源连接成功
- ✅ LogQL 查询能返回带标签的日志行
3.6 常见问题与排障
| 现象 | 可能原因 | 解决措施 |
|---|---|---|
Promtail 日志报 connection refused |
Loki 容器未就绪或网络不通 | 检查 docker compose logs loki,确认 Loki 启动完成 |
| Grafana 数据源测试失败 | URL 使用了 localhost 而非容器名 loki |
将 URL 改为 http://loki:3100 |
| 查询返回空结果 | 日志文件路径或标签不匹配 | 检查 Promtail 配置中 __path__ 是否正确,查看 Promtail 日志确认文件是否被 tail |
| Loki 磁盘空间增长过快 | 未配置日志保留策略 | 在 limits_config 中添加 retention_period: 168h(7天) |
安全提醒:本部署未启用 TLS 和认证,切勿在公网或生产环境直接使用。建议在 docker-compose.yml 中为 Grafana 设置强密码,并为 Loki 启用
auth_enabled: true 及反向代理。