环境搭建与基础配置:Docker Compose部署Prometheus Stack

好,咱们直接进入正题。这一章,我带你亲手把Prometheus监控栈搭起来。说实话,很多新手在这一步就卡住了——不是配置文件写错,就是端口冲突,折腾半天连个数据都看不到。别急,跟着我的节奏来,保证一次跑通。

为什么选Docker Compose?

我个人习惯用Docker Compose来部署Prometheus Stack。原因很简单:可复现、易管理、好迁移。你想想看,如果每台机器都手动装一遍Prometheus、Grafana、Alertmanager,那运维成本得多高?

我在项目中遇到过最典型的情况:开发环境搭好了,测试环境又得重来一遍。有了Compose文件,一条命令搞定所有服务。说白了,这就是运维的「一次编写,到处运行」。

网络规划与端口映射

先别急着写代码,咱们得把网络想清楚。我见过太多人上来就写ports: "9090:9090",结果跟宿主机上已有的服务冲突了。

这里我建议的规划方案:

服务 内部端口 映射端口 说明
Prometheus 9090 19090 避开常见端口
Grafana 3000 13000 防止跟开发环境冲突
Alertmanager 9093 19093 告警管理专用
Node Exporter 9100 19100 主机指标采集

为什么要用19090而不是9090?嗯,这里要注意:很多团队会在宿主机上跑一些Java应用,它们默认就占用了8080、9090这些端口。我曾经因为端口冲突排查了整整一个下午,最后发现是Jenkins占用了9090。从那以后,我所有映射端口都加了个1前缀。

数据持久化配置

容器一重启数据就丢了?这绝对是新手最容易踩的坑。Prometheus默认把数据写在容器内部,一旦容器被删除,所有历史指标全部消失。

解决方案很简单:挂载宿主机目录。我习惯在宿主机上创建这样一个目录结构:

/data/prometheus/
├── prometheus/
│   └── data/
├── grafana/
│   └── data/
└── alertmanager/
    └── data/

然后在Compose文件里用volumes挂载。这样即使容器挂了,数据还在宿主机上。我建议你养成习惯:所有有状态的服务,必须做数据持久化

完整的Docker Compose文件

好了,理论说完了,直接上代码。这是我经过多次迭代后沉淀下来的版本:

version: '3.8'

networks:
  monitor-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

services:
  prometheus:
    image: prom/prometheus:v2.45.0
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - /data/prometheus/prometheus/data:/prometheus
    ports:
      - "19090:9090"
    networks:
      monitor-net:
        ipv4_address: 172.20.0.10
    restart: unless-stopped

  grafana:
    image: grafana/grafana:10.0.3
    container_name: grafana
    volumes:
      - /data/prometheus/grafana/data:/var/lib/grafana
    ports:
      - "13000:3000"
    networks:
      monitor-net:
        ipv4_address: 172.20.0.11
    restart: unless-stopped

  alertmanager:
    image: prom/alertmanager:v0.25.0
    container_name: alertmanager
    volumes:
      - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
      - /data/prometheus/alertmanager/data:/alertmanager
    ports:
      - "19093:9093"
    networks:
      monitor-net:
        ipv4_address: 172.20.0.12
    restart: unless-stopped

  node-exporter:
    image: prom/node-exporter:v1.6.0
    container_name: node-exporter
    ports:
      - "19100:9100"
    networks:
      monitor-net:
        ipv4_address: 172.20.0.13
    restart: unless-stopped

关键点说明:

  • 使用networks指定了子网172.20.0.0/16,避免跟Docker默认网段冲突
  • 每个服务都分配了固定IP,方便后续配置中直接引用
  • restart: unless-stopped保证服务异常退出后自动重启

Prometheus配置文件

有了Compose文件还不够,Prometheus需要知道自己该采集哪些目标。这是我的prometheus.yml

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['172.20.0.13:9100']

  - job_name: 'alertmanager'
    static_configs:
      - targets: ['172.20.0.12:9093']

这里有个小技巧:scrape_interval我设成了15秒。为什么不是默认的1分钟?因为监控系统需要快速发现异常。但也不能设得太短,否则会对目标机器造成压力。15秒是我在项目中验证过的平衡点。

启动与验证

所有文件准备好后,执行一条命令:

docker-compose up -d

然后检查服务状态:

docker-compose ps

你应该看到四个服务都是Up状态。接着打开浏览器:

  • Prometheus UI:http://宿主机IP:19090
  • Grafana:http://宿主机IP:13000(默认账号admin/admin)
  • Alertmanager:http://宿主机IP:19093

避坑指南:我曾经在部署时发现Grafana一直报Permission denied。排查了半天,原来是宿主机上/data/prometheus/grafana/data目录的权限不对。Grafana容器内的用户是472,所以需要执行:

chown -R 472:472 /data/prometheus/grafana/data

记住这个教训:挂载目录的权限一定要跟容器内用户匹配

核心架构图

为了让你更直观地理解整个架构,我画了一张图:

Prometheus Stack 架构图 monitor-net (172.20.0.0/16) Prometheus 172.20.0.10:9090 端口映射: 19090 Grafana 172.20.0.11:3000 端口映射: 13000 Alertmanager 172.20.0.12:9093 端口映射: 19093 Node Exporter 172.20.0.13:9100 采集指标 数据源 告警推送 数据持久化:/data/prometheus/ 目录挂载到宿主机

这张图清晰地展示了四个服务之间的协作关系。Node Exporter负责采集主机指标,Prometheus负责存储和查询,Grafana负责可视化,Alertmanager负责告警。它们通过monitor-net网络相互通信。

验证是否成功

部署完成后,我习惯做三件事来验证:

  1. 检查Prometheus Targets:访问http://宿主机IP:19090/targets,看所有目标是否都是UP状态
  2. 检查Grafana数据源:登录Grafana,添加Prometheus数据源,URL填http://172.20.0.10:9090,点击「Save & Test」
  3. 检查Alertmanager状态:访问http://宿主机IP:19093/#/status,确认服务正常运行

重要提醒:如果Grafana连接Prometheus失败,八成是网络问题。检查一下:

  • 两个服务是否在同一个Docker网络里
  • Prometheus的IP地址是否写对了(是容器IP,不是宿主机IP)
  • 防火墙有没有拦截19090端口

好了,环境搭建就到这里。这套配置我用了两年多,在十几个项目里验证过,稳定性没得说。你照着做,应该半小时内就能跑起来。


公众号:蓝海资料掘金营,微信deep3321