Prometheus 3.x Docker Compose 部署指南

使用 Docker Compose 部署单节点 Prometheus 3.15.0(官方镜像 `prom/prometheus:v3.15.0`,实测与 latest 一致),含数据持久化、配置挂载、wget 健康检查(实测镜像内无 curl)、日志限制,并给出等价的 `docker run`。已在 `/opt/data/ops/prometheus`...

PrometheusPrometheus容器化2026/09/27

Prometheus 3.x Docker Compose 部署指南

目标:使用 Docker Compose 部署单节点 Prometheus 3.15.0(官方镜像 prom/prometheus:v3.15.0,实测与 latest 一致),含数据持久化、配置挂载、wget 健康检查(实测镜像内无 curl)、日志限制,并给出等价的 docker run。已在 /opt/data/ops/prometheus 目录实测通过(容器 prometheus-3-x,宿主机端口 19090)。

一、环境信息

  • Docker 版本:Docker Engine 29.4.1(Compose v2)
  • 镜像版本:prom/prometheus:v3.15.0(实测 Prometheus 3.15.0,最新 3.x)
  • 容器名称:prometheus-3-x
  • 端口映射:宿主机 19090 → 容器 9090
  • 数据目录:宿主机 /opt/data/ops/prometheus/data(持久化,实测重启后数据保留)
  • 配置文件:宿主机 /opt/data/ops/prometheus/conf/prometheus.yml(含规则文件 alerts.yml 挂载)
  • 部署文件:/opt/data/ops/prometheus/docker-compose.yaml

⚠️ 镜像源说明:docker.io/prom/prometheus:v3.15.0 实测直拉成功。若直拉失败,用 daocloud 加速源:m.daocloud.io/docker.io/prom/prometheus:v3.15.0。

⚠️ 镜像内工具实测:prom/prometheus 镜像没有 curl(/bin/curl: No such file or directory),仅有 /bin/wget,且无 bash(只有 sh)——健康检查必须用 wget,docker exec 需用 sh。

二、镜像选型说明

镜像标签对应版本说明
prom/prometheus:v3.15.03.15.0(实测)推荐,锁定最新 3.x 版本
prom/prometheus:latest当前最新稳定版(实测同为 3.15.0)跟随更新,生产建议锁定具体标签
prom/prometheus:v3.0.03.0.03.x 首个版本

三、前置条件

  • Docker Engine + Compose 插件
  • 已规划数据与配置目录(/opt/data/ops/prometheus/{data,conf})
  • 镜像内进程以 nobody(uid=65534) 运行,数据目录需该用户可写(实测踩坑,见"七、常见问题"的 7.2)

四、部署步骤

4.1 创建目录与配置

mkdir -p /opt/data/ops/prometheus/{data,conf}
cd /opt/data/ops/prometheus

创建 /opt/data/ops/prometheus/conf/prometheus.yml(基础版,含规则文件声明与 OTLP 配置):

# Prometheus 3.x 单节点基础配置(Docker Compose 挂载)
global:
  scrape_interval: 15s        # 抓取间隔
  evaluation_interval: 15s    # 规则评估间隔

alerting:
  alertmanagers:
    - static_configs:
        - targets: []
          # - "alertmanager:9093"

rule_files:
  - "alerts.yml"              # 规则文件(记录规则+告警规则)

otlp:
  translation_strategy: NoUTF8EscapingWithSuffixes   # 保留 OTLP UTF-8 指标名(3.x)

scrape_configs:
  - job_name: "prometheus"    # 抓取自身
    static_configs:
      - targets: ["localhost:9090"]

💡 命令解释:{data,conf} 为 shell 大括号展开,一次创建两个目录;otlp 段配合 --web.enable-otlp-receiver 使用(见《Prometheus 3.x 配置参数详解》)。

4.2 编写 docker-compose.yaml

# =============================================================================
# Prometheus 3.x Docker Compose 部署文件(单节点)
# 镜像版本:prom/prometheus:v3.15.0(实测 Prometheus 3.15.0,对应最新 3.x 系列)
# 使用方式:cd /opt/data/ops/prometheus && docker compose up -d
# 数据目录 ./data 持久化,配置挂载 ./conf/prometheus.yml,修改后热加载无需重启容器
# =============================================================================

services:
  prometheus:
    # 官方镜像(docker.io 直拉失败时,可用 daocloud 加速源 m.daocloud.io/docker.io/prom/prometheus:v3.15.0)
    image: prom/prometheus:v3.15.0

    # 容器名称,方便 docker ps / docker logs 定位
    container_name: prometheus-3-x

    # 重启策略:容器异常退出时自动重启(除非手动 stop)
    restart: unless-stopped

    # ---- 启动参数(等价于命令行参数,可用 `prometheus --help` 查看全部)----
    # --web.enable-lifecycle 开启 HTTP 热加载(curl -X POST http://localhost:19090/-/reload)
    # --storage.tsdb.retention.time 数据保留时长(默认 15d,此处显式声明)
    # --web.enable-otlp-receiver 开启 OTLP 写入端点(/api/v1/otlp/v1/metrics,UTF-8 指标名实测)
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --storage.tsdb.retention.time=15d
      - --web.enable-lifecycle
      - --web.enable-otlp-receiver

    # ---- 端口映射:宿主机19090 -> 容器9090 ----
    ports:
      - "19090:9090"

    # ---- 数据持久化(重要)----
    # ./data 为宿主机数据目录(容器内 /prometheus),重启容器数据不丢失;
    # 注意:镜像内以 nobody(uid=65534) 运行,./data 需 nobody 可写(chown 65534:65534)
    volumes:
      - ./data:/prometheus
      # ---- 配置文件挂载(重要)----
      # 编辑 ./conf/prometheus.yml 后执行
      #   curl -X POST http://localhost:19090/-/reload
      # 即可热加载(需 --web.enable-lifecycle),无需重启容器
      - ./conf/prometheus.yml:/etc/prometheus/prometheus.yml
      # ---- 规则文件挂载(prometheus.yml 中 rule_files 声明后生效)----
      - ./conf/alerts.yml:/etc/prometheus/alerts.yml

    # ---- 健康检查:镜像内无 curl(实测仅有 /bin/wget),用 wget 探测 /-/healthy ----
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
      interval: 15s      # 每 15 秒检查一次
      timeout: 5s        # 单次检查超时
      retries: 5         # 连续 5 次失败视为不健康
      start_period: 10s  # 启动后 10 秒才开始检查

    # 容器日志大小限制,防止磁盘被日志占满
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

💡 说明:--web.enable-lifecycle 为 3.x 运维标配(否则 /-/reload 实测返回 403);otlp 段与 --web.enable-otlp-receiver 为可选能力,不需要 UTF-8 指标名可移除。healthcheck 用 wget 是因为镜像实测无 curl(见"七、常见问题"的 7.1)。

4.3 调整数据目录权限并启动

# 镜像内 nobody(65534) 需可写数据目录(实测不调整则 TSDB 无法写入)
docker run --rm -v /opt/data/ops/prometheus/data:/data alpine chown -R 65534:65534 /data
docker compose up -d
docker compose ps

实测输出:

 Container prometheus-3-x Started
NAME             IMAGE                     COMMAND                   SERVICE      STATUS                   PORTS
prometheus-3-x   prom/prometheus:v3.15.0   "/bin/prometheus --c…"   prometheus   Up 10 seconds (healthy)   0.0.0.0:19090->9090/tcp

💡 命令解释:chown -R 65534:65534 把数据目录属主改为 nobody(容器内 prometheus 运行用户);up -d 后台创建并启动;ps 查看状态,(healthy) 表示 wget 健康检查通过。

💡 说明:健康检查实测生效——容器启动约 8 秒即显示 (healthy)。

4.4 验证服务

curl -s http://localhost:19090/-/healthy
curl -s http://localhost:19090/metrics | wc -l
curl -s "http://localhost:19090/api/v1/query?query=up"

实测输出:

Prometheus Server is Healthy.
1198
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"up","instance":"localhost:9090","job":"prometheus"},"value":[1790458430.393,"1"]}]}}

💡 命令解释:/-/healthy 返回 Prometheus Server is Healthy. 即就绪;/metrics 为自监控指标;up 查询验证抓取链路(值 1 = 抓取成功)。

4.5 数据持久化验证

docker restart prometheus-3-x
docker exec prometheus-3-x sh -c 'ls /prometheus/wal/'
curl -s --get "http://localhost:19090/api/v1/query" --data-urlencode 'query=up{job="prometheus"}'

实测输出:

00000000
00000001
00000002
重启后 up 查询: [1790459179.717, '1']

💡 说明:./data:/prometheus 挂载持久化 WAL/TSDB,重启后 WAL 段文件仍在并正常回放,查询正常。注意镜像无 bash,docker exec 需用 sh -c。

4.6 等价的 docker run

docker run -d --name prometheus-3-x \
  -p 19090:9090 \
  -v /opt/data/ops/prometheus/data:/prometheus \
  -v /opt/data/ops/prometheus/conf/prometheus.yml:/etc/prometheus/prometheus.yml \
  -v /opt/data/ops/prometheus/conf/alerts.yml:/etc/prometheus/alerts.yml \
  --restart unless-stopped \
  prom/prometheus:v3.15.0 \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/prometheus \
  --storage.tsdb.retention.time=15d \
  --web.enable-lifecycle \
  --web.enable-otlp-receiver

💡 命令解释:-p 19090:9090 端口映射;-v 挂载数据与配置;--restart unless-stopped 异常自动重启;镜像默认 entrypoint 为 /bin/prometheus,其后参数即命令行 flag。健康检查在 docker run 下需用 --health-cmd 另行指定。

五、配置说明

5.1 热加载(--web.enable-lifecycle)

# 修改 conf/prometheus.yml 后热加载,无需重启容器(实测返回 200)
curl -s -X POST http://localhost:19090/-/reload -o /dev/null -w "%{http_code}"

5.2 规则文件(conf/alerts.yml 示例)

groups:
  - name: example-group
    interval: 15s
    rules:
      - record: job:up:sum          # 记录规则:预计算
        expr: sum by (job) (up)
      - alert: InstanceDown         # 告警规则
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "实例 {{ $labels.instance }} 已下线"

实测加载后 /api/v1/rules 返回 group: example-group | rules: [('recording', 'job:up:sum'), ('alerting', 'InstanceDown')]。

六、注意事项

  • 镜像无 curl 无 bash:健康检查用 wget --spider,进入容器用 docker exec -it prometheus-3-x sh
  • 数据目录权限:镜像以 nobody(65534) 运行,./data 必须先 chown 65534:65534(实测不处理则容器启动后 TSDB 写失败)
  • --web.enable-lifecycle 默认关闭,不加则热加载 403;admin API 默认关闭(需 --web.enable-admin-api)
  • 生产环境建议锁定具体 tag(如 v3.15.0),并配合 external_labels、告警规则与远程存储
  • 端口 19090 避免与宿主机其他 9090 服务冲突

七、常见问题

7.1 healthcheck 用 curl 一直失败 / 镜像内没有 curl

原因:实测 prom/prometheus 镜像只有 /bin/wget,无 curl(ls: /bin/curl: No such file or directory),Compose healthcheck 里写 curl 会报 executable file not found。

解决:改用 wget:

healthcheck:
  test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]

7.2 容器启动后 TSDB 报 permission denied / 数据目录写不进去

原因:镜像内以 nobody(uid=65534) 运行,宿主机 ./data 若为 root 属主则无法写入(实测踩坑)。

解决:

docker run --rm -v /opt/data/ops/prometheus/data:/data alpine chown -R 65534:65534 /data

7.3 docker exec -it prometheus-3-x bash 报 not found

原因:官方镜像基于 busybox,无 bash(实测 exec: "bash": executable file not found in $PATH)。

解决:用 sh:

docker exec -it prometheus-3-x sh

7.4 配置修改后热加载不生效(403)

原因:未加 --web.enable-lifecycle(实测未加时 /-/reload 返回 403)。

解决:compose command 中加 --web.enable-lifecycle,再执行 curl -X POST http://localhost:19090/-/reload。

7.5 daocloud 加速拉取镜像

docker pull m.daocloud.io/docker.io/prom/prometheus:v3.15.0
# 使用时可整体替换 image 字段,或打 tag 后使用
docker tag m.daocloud.io/docker.io/prom/prometheus:v3.15.0 prom/prometheus:v3.15.0

八、卸载方式

cd /opt/data/ops/prometheus
docker compose down                # 停止并移除容器(数据保留在 ./data)
docker rm -f prometheus-3-x        # 如需强制删除
rm -rf /opt/data/ops/prometheus    # 删除全部数据与配置(确认备份后)

九、参考链接


本文档由 www.quzuo.net 平台开发