Docker 部署 Loki + Promtail + Grafana 日志监控栈
通过 Docker Compose 快速搭建日志集中采集与可视化平台,适配 auditd 审计日志场景。
架构概览
宿主机
├── /var/log/syslog ──┐
└── /var/log/audit/audit.log ──┤
▼
Promtail(采集)
│
▼
Loki(存储)
│
▼
Grafana(可视化)
| 服务 | 镜像 | 端口 | 说明 |
|---|---|---|---|
| Loki | grafana/loki:2.9.4 |
3100 |
日志存储与查询引擎 |
| Promtail | grafana/promtail:2.9.4 |
9080 |
日志采集 agent |
| Grafana | grafana/grafana:10.3.3 |
3000 |
可视化看板 |
目录结构
loki-docker/
├── docker-compose.yml
└── config/
├── loki.yml # Loki 主配置
├── promtail.yml # Promtail 采集规则
└── grafana-datasource.yml # Grafana 数据源自动配置
配置文件说明
1. docker-compose.yml
yaml
networks:
loki:
driver: bridge
services:
# ─── Loki:日志存储 ───
loki:
image: grafana/loki:2.9.4
container_name: loki
ports:
- "3100:3100"
volumes:
- ./config/loki.yml:/etc/loki/loki.yml
- loki-data:/loki
command: -config.file=/etc/loki/loki.yml
networks:
- loki
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3100/ready || exit 1"]
interval: 10s
timeout: 5s
retries: 5
# ─── Promtail:日志采集 ───
promtail:
image: grafana/promtail:2.9.4
container_name: promtail
hostname: ub-jack # ← 改为当前机器名
ports:
- "9080:9080"
volumes:
- ./config/promtail.yml:/etc/promtail/promtail.yml
- /var/log:/var/log:ro # 挂载宿主机日志(只读)
command: -config.file=/etc/promtail/promtail.yml
networks:
- loki
restart: unless-stopped
depends_on:
loki:
condition: service_healthy
# ─── Grafana:可视化 ───
grafana:
image: grafana/grafana:10.3.3
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=changeme123 # 上线前务必修改
- GF_AUTH_ANONYMOUS_ENABLED=false
volumes:
- grafana-data:/var/lib/grafana
- ./config/grafana-datasource.yml:/etc/grafana/provisioning/datasources/loki.yml
networks:
- loki
restart: unless-stopped
depends_on:
loki:
condition: service_healthy
volumes:
loki-data:
grafana-data:
⚠️ 多台机器部署时 ,每台机器只需修改
hostname:为各自的机器名,其余配置不变。
2. config/loki.yml
yaml
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
instance_addr: 127.0.0.1
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
ingestion_rate_mb: 10
ingestion_burst_size_mb: 20
max_query_lookback: 720h # 最长查询 30 天
retention_period: 720h # 日志保留 30 天
关键参数说明:
| 参数 | 值 | 说明 |
|---|---|---|
auth_enabled |
false |
单机部署无需认证,多租户场景改为 true |
retention_period |
720h |
日志保留 30 天,按需调整 |
ingestion_rate_mb |
10 |
每秒最大写入速率(MB) |
max_query_lookback |
720h |
查询历史最长范围 |
3. config/promtail.yml
yaml
server:
http_listen_port: 9080
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# ─── 采集 syslog(含 auditd via rsyslog) ───
- job_name: syslog
static_configs:
- targets: [localhost]
labels:
job: syslog
host: ${HOSTNAME} # 自动读取容器 hostname
__path__: /var/log/syslog
pipeline_stages:
- match:
selector: '{job="syslog"}'
stages:
- regex:
expression: '(?P<audit_type>type=[A-Z_]+)?.*(?P<audit_key>key="[^"]+")?'
- labels:
audit_type:
audit_key:
# ─── 采集 audit.log 原始文件 ───
- job_name: auditd
static_configs:
- targets: [localhost]
labels:
job: auditd
host: ${HOSTNAME} # 自动读取容器 hostname
__path__: /var/log/audit/audit.log
pipeline_stages:
- regex:
expression: 'type=(?P<audit_type>[A-Z_]+).*(?:key="(?P<audit_key>[^"]+)")?'
- labels:
audit_type:
audit_key:
pipeline_stages 说明:
regex:从日志行提取audit_type(事件类型)和audit_key(规则 key)labels:将提取的字段设为 Loki 标签,在 Grafana 中可直接过滤
4. config/grafana-datasource.yml
yaml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
url: http://loki:3100
isDefault: true
jsonData:
maxLines: 1000
timeout: 60
此文件在 Grafana 启动时自动注册 Loki 数据源,无需手动添加。
部署步骤
前置条件
- Docker >= 20.10
- Docker Compose >= 2.0
- 宿主机已安装并运行 auditd
第一步:克隆配置
bash
# 将整个 loki-docker 目录上传到目标机器
scp -r loki-docker/ user@<服务器IP>:/opt/loki-docker
第二步:修改机器名
编辑 docker-compose.yml,将 hostname 改为当前机器名:
bash
cd /opt/loki-docker
nano docker-compose.yml
# 找到 hostname: ub-jack,改为实际机器名
第三步:启动服务
bash
docker compose up -d
第四步:验证服务状态
bash
# 查看所有容器状态
docker compose ps
# 验证 Loki 就绪
curl http://localhost:3100/ready
# 验证 Promtail 正在推送日志
curl -s http://localhost:9080/metrics | grep promtail_sent_entries_total
期望输出:
promtail_sent_entries_total{host="loki:3100"} 12345 ← 数值 > 0 即正常
访问 Grafana
浏览器打开:http://<服务器IP>:3000
| 项目 | 默认值 |
|---|---|
| 用户名 | admin |
| 密码 | changeme123 |
⚠️ 登录后请立即修改密码:右上角头像 → Profile → Change Password
查询 auditd 日志(LogQL)
进入 Grafana → Explore → 选择 Loki 数据源:
logql
# 查看所有 auditd 日志
{job="auditd"}
# 过滤指定主机
{job="auditd", host="ub-jack"}
# 查看 sudo 使用记录
{job="auditd"} |= "sudo_usage"
# 查看身份文件变更(/etc/passwd 等)
{job="auditd"} |= "identity"
# 查看登录事件
{job="auditd"} |= "USER_LOGIN"
# 统计各事件类型数量(近 5 分钟)
sum by (audit_key) (count_over_time({job="auditd"}[5m]))
常用运维命令
bash
# 查看实时日志
docker compose logs -f
# 单独查看某个服务日志
docker logs grafana -f
docker logs loki -f
docker logs promtail -f
# 重启单个服务
docker compose restart promtail
# 停止所有服务
docker compose down
# 停止并清除数据卷(慎用,会删除所有日志数据)
docker compose down -v
多台机器部署
每台机器复制完整的 loki-docker 目录,只修改 docker-compose.yml 中的一处:
yaml
# 机器 A
hostname: web-server-01
# 机器 B
hostname: db-server-01
# 机器 C
hostname: app-server-01
Loki 和 Grafana 只需部署在一台中央服务器上,其他机器只部署 Promtail 即可。

常见问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
| Grafana 启动失败(exit code 1) | 数据目录权限不足 | docker compose down -v && docker compose up -d |
| Promtail 连接不上 Loki | Loki 未就绪 | 等待 Loki healthcheck 通过后 Promtail 自动重连 |
| 日志查询为空 | 采集路径不存在 | 确认 /var/log/audit/audit.log 在宿主机存在 |
| host 标签显示为容器 ID | 未设置 hostname | 在 docker-compose.yml 中设置 hostname: |