一、Loki + Promtail + Grafana 来收集并可视化 Nginx
使用 Docker Compose 搭建 Loki + Promtail + Grafana 来收集并可视化 Nginx 日志,是一个轻量级且高效的方案。以下是完整的部署步骤:
1. 准备 Nginx 容器
为了让 Promtail 能够读取 Nginx 的日志,需要将 Nginx 的日志目录挂载到宿主机上。
在你的业务 docker-compose.yml 中,配置 Nginx 服务并映射日志目录:
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
# 将宿主机的 ./nginx/logs 目录挂载到容器内的 /var/log/nginx
- ./nginx/logs:/var/log/nginx
restart: always
2. 创建 Loki 配置文件
创建 loki-config.yml 文件,配置 Loki 的本地存储和保留策略(例如保留 7 天):
auth_enabled: false
server:
http_listen_port: 3100
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: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /loki/boltdb-shipper-active
cache_location: /loki/boltdb-shipper-cache
cache_ttl: 24h
shared_store: filesystem
limits_config:
retention_period: 168h # 7天
3. 创建 Promtail 配置文件
创建 promtail-config.yml 文件,配置采集规则,读取挂载出来的 Nginx 日志并打上标签:
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
static_configs:
- targets:
- localhost
labels:
job: nginx_access
__path__: /var/log/nginx/access.log
- targets:
- localhost
labels:
job: nginx_error
__path__: /var/log/nginx/error.log
4. 编写监控栈的 Docker Compose 配置
创建一个专门用于日志监控的 docker-compose.yml 文件:
networks:
loki_net:
driver: bridge
name: loki_net
services:
loki:
image: grafana/loki:2.9.2
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
- ./loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: always
promtail:
image: grafana/promtail:2.9.2
container_name: promtail
volumes:
- ./promtail-config.yml:/etc/promtail/config.yml
# 关键:将 Nginx 的日志目录只读挂载到 Promtail 容器中
- ./nginx/logs:/var/log/nginx:ro
command: -config.file=/etc/promtail/config.yml
depends_on:
- loki
restart: always
grafana:
image: grafana/grafana:9.5.5
container_name: grafana
ports:
- "3000:3000"
volumes:
- ./grafana-data:/var/lib/grafana
restart: always
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
# 将宿主机的 ./nginx/logs 目录挂载到容器内的 /var/log/nginx
- ./nginx/logs:/var/log/nginx
restart: always
增加权限
5. 启动服务
在包含上述 docker-compose.yml 的目录下,运行以下命令启动所有服务:
docker-compose up -d
6. 在 Grafana 中配置与查看
- 浏览器访问
http://<你的服务器IP>:3000,使用默认账号密码admin/admin登录。 - 进入 Configuration -> Data sources,点击 Add data source,选择 Loki。
- 在 URL 处填写
http://loki:3100,点击 Save & Test,提示成功即可。 - 进入左侧菜单的 Explore,在顶部选择 Loki 数据源,输入查询语句:
- 查看访问日志:
{job="nginx_access"} - 查看错误日志:
{job="nginx_error"}
- 查看访问日志:
- 点击 Run query 即可看到 Nginx 的实时日志流。你也可以在 Grafana 面板库中导入 Nginx 专属的 Dashboard(如 ID:
11055)来实现更直观的可视化监控。


二、通过docker socket读取Loki + Promtail + Grafana 来收集并可视化 Nginx
docker-compose.yaml
[root@ceph1 sot]# cat docker-compose.yaml
networks:
loki_net:
driver: bridge
name: loki_net
services:
# 1. Loki:日志存储引擎
loki:
image: grafana/loki:2.9.2
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
- loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: always
# 2. Promtail:日志采集器(通过 Docker Socket 采集)
promtail:
image: grafana/promtail:2.9.2
container_name: promtail
volumes:
- /var/run/docker.sock:/var/run/docker.sock # 关键!挂载 Docker Socket
- ./promtail-config.yml:/etc/promtail/config.yaml
command: -config.file=/etc/promtail/config.yaml
restart: always
# 3. Grafana:可视化面板
grafana:
image: grafana/grafana:9.5.5
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin # 默认密码
volumes:
- grafana-data:/var/lib/grafana
restart: always
# 4. 示例 Nginx 服务(无需挂载日志目录)
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
restart: always
volumes:
loki-data:
grafana-data:
promtail.yml 配置文件
[root@ceph1 sot]# cat promtail-config.yml
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: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
target_label: 'service'
loki.yml配置文件 保持不变
[root@ceph1 sot]# cat loki-config.yml
auth_enabled: false
server:
http_listen_port: 3100
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: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /loki/boltdb-shipper-active
cache_location: /loki/boltdb-shipper-cache
cache_ttl: 24h
shared_store: filesystem
limits_config:
retention_period: 168h # 7天
启动 docker-compose up -d
访问

三、告警钉钉版本alertmanager
所有文件

docker-compose.yml
networks:
loki_net:
driver: bridge
name: loki_net
services:
# 1. Loki:日志存储 + 告警规则评估(Ruler)
loki:
image: grafana/loki:2.9.2
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
- ./rules:/etc/loki/rules
- loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: always
# 2. Promtail:通过 Docker Socket 采集容器日志
promtail:
image: grafana/promtail:2.9.2
container_name: promtail
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./promtail-config.yaml:/etc/promtail/config.yaml
command: -config.file=/etc/promtail/config.yaml
restart: always
# 3. Alertmanager:独立告警通知服务
alertmanager:
image: prom/alertmanager:v0.26.0
container_name: alertmanager
ports:
- "9093:9093"
volumes:
- ./alertmanager-config.yml:/etc/alertmanager/alertmanager.yml
- alertmanager-data:/alertmanager
command: --config.file=/etc/alertmanager/alertmanager.yml --storage.path=/alertmanager
restart: always
# 4. Grafana:可视化面板(可选,用于查看日志和告警状态)
grafana:
image: grafana/grafana:9.5.5
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
restart: always
# 4. 示例 Nginx 服务(无需挂载日志目录)
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
restart: always
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
dingtalk-webhook:
image: timonwong/prometheus-webhook-dingtalk:v2.1.0
container_name: dingtalk-webhook
restart: always
ports:
- "8060:8060"
volumes:
- ./dingding-config.yaml:/etc/prometheus-webhook-dingtalk/config.yml:ro
volumes:
loki-data:
alertmanager-data:
grafana-data:
promtail-config.yaml
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: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
pipeline_stages:
- regex:
# 精准匹配你当前日志格式
expression: '^(?P<remote_addr>\S+) \S+ \S+ \[(?P<time>.+?)\] "(?P<method>\S+) (?P<path>\S+) \S+" (?P<status>\d{3}) \d+ ".+?" ".+?"'
# 将捕获的status存入日志标签,Loki可直接筛选
- labels:
status:
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
target_label: 'service'
loki-config.yaml
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
ruler:
alertmanager_url: http://alertmanager:9093 # ← 关键!指向 Alertmanager 容器
storage:
type: local
local:
directory: /etc/loki/rules
rule_path: /tmp/loki/rules-temp
enable_api: true
enable_alertmanager_v2: true
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
alertmanager-config.yml
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'job']
group_wait: 30s
group_interval: 5m
repeat_interval: 1h
receiver: 'webhook'
receivers:
- name: 'webhook'
webhook_configs:
- url: 'http://dingtalk-webhook:8060/dingtalk/webhook1/send'
send_resolved: true
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'job']
Loki 告警规则文件 ( rules/fake/nginx-alerts.yml) 必须要有fake这个目录
定义具体的告警逻辑,例如 Nginx 5xx 错误率过高:
groups:
- name: nginx-alerts
rules:
- alert: NginxHigh5xxRate
expr: |
sum(rate({container="nginx"} | status >= 500 [1m]))
/
sum(rate({container="nginx"} [1m])) > 0
> 0.05
for: 30s
labels:
severity: critical
annotations:
summary: "{告警}Nginx 5xx 错误率超过 5%"
description: "{告警}过去 1 分钟内,Nginx 5xx 错误请求占比超过 5%,当前值: {{ $value }}"
nginx.conf 配置文件
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# 新增500接口
location /500 {
return 500;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
钉钉配置文件 dingding-config.yaml
targets:
webhook1:
url: https://oapi.dingtalk.com/robot/send?access_token=a9ae2327f363d0e27497203626793e6b64ae594b9d0e17bbb7c034c5eb3c6ec1
secret: SEC7d23961c56aa0060fd9b29c06321f2808387578f51a4eb8ebbd1c3e4a75054c1
启动与验证
- 创建目录结构:
mkdir -p rules/fake
touch rules/fake/nginx-alerts.yml
- 启动所有服务:
docker-compose up -d
- 验证告警是否生效:
- 访问
http://localhost:3100/loki/api/v1/rules查看 Loki 是否加载了规则。 - 访问
http://localhost:9093查看 Alertmanager 是否接收到告警。 - 触发一个 5xx 错误(如访问一个不存在的页面),等待 2 分钟后检查 Alertmanager 是否发出通知。
- 访问
完整告警链路总结
整个流程分为四个阶段,数据流向如下:
1. 数据采集与存储(眼睛)
- 源头:业务服务器(如 Nginx)产生日志文件。
- 采集:Promtail 实时监控日志文件变化,将日志流式传输给 Loki。
- 存储:Loki 接收并索引这些日志数据,等待被查询或评估。
2. 规则评估与触发(大脑)—— 核心环节
- 加载规则:Loki (Ruler 组件) 启动时,会去指定目录(如
/etc/loki/rules/fake/)加载你写的.yml告警规则文件。 - 实时计算:Ruler 周期性(默认 1 分钟)执行 LogQL 语句(例如
count_over_time(...))。 - 触发告警:如果计算结果满足阈值(例如 5xx 错误数 > 5),Loki 就会生成一个标准的“告警事件”。
3. 告警路由与分发(中枢神经)
- 发送:Loki 将生成的告警事件通过 HTTP POST 请求发送给 Alertmanager。
- 处理:Alertmanager 接收告警,根据配置进行分组、静默或抑制处理。
- 转发:Alertmanager 匹配到 Webhook 路由,将告警 JSON 数据包转发给钉钉适配器。
4. 消息格式化与通知(嘴巴)
- 接收:prometheus-webhook-dingtalk 监听端口(如 8060),收到 Alertmanager 发来的数据。
- 翻译:它将复杂的 Prometheus/Loki 格式 JSON 转换为钉钉机器人支持的 Markdown 或 Text 格式。
- 触达:调用钉钉 API,最终在你的钉钉群里弹出消息。

1919

被折叠的 条评论
为什么被折叠?



