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 查询日志 → 展示图表/表格/告警

下图展示了日志从产生到可视化的完整数据流:

Loki + Promtail + Grafana 数据流架构图 Loki + Promtail + Grafana 数据流架构 应用日志 /var/log/*.log Promtail 日志采集 + 推送 Loki 存储 + 查询引擎 Grafana 可视化 + 告警 读取日志 HTTP Push LogQL 查询 仪表盘 ⚠ 注意 Promtail 必须与日志源同机部署
架构要点: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 数据源:

  1. 进入 Configuration → Data Sources → Add data source。
  2. 选择 Loki,在 URL 字段填入 http://loki:3100。
  3. 点击 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 及反向代理。