Graphite 1.1.10 Docker Compose 部署指南

官方一体化镜像 graphiteapp/graphite-statsd:1.1.10-5 的 Compose 从零部署:栈健康检查、端口规划、数据持久化、2003 明文打点与 statsd UDP 埋点端到端验证、render API 与 Web UI 曲线确认及常见问题排障。

GraphiteGraphite监控Docker2026/10/20

Graphite 1.1.10 Docker Compose 部署指南

目标:在一台 Ubuntu 服务器上用官方一体化镜像 graphiteapp/graphite-statsd:1.1.10-5 完成从零到可用的 Graphite 监控系统部署:Compose 编排、服务健康检查、向 carbon 2003 端口打点、并通过 render API 与 Web UI 端到端验证曲线数据。全文命令与回显均在 Ubuntu 22.04.4 LTS + Docker Compose v5.5.1 环境实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64)
  • Docker Engine:29.8.1;Docker Compose:v5.5.1(docker compose 插件形态)
  • Graphite 版本:graphite-web / carbon / whisper 三件套 1.1.10,官方一体化镜像 graphiteapp/graphite-statsd:1.1.10-5(镜像内含 nginx、graphite-web、carbon-cache、carbon-aggregator、statsd,由 runit 托管)
  • 部署目录:/opt/graphite-deploy(本文示例根目录,下同)
  • 服务端口规划:Web 8128、carbon 明文 8129、carbon pickle 8132、statsd UDP 8133(宿主侧端口可按实际情况替换,容器内端口见环境变量表后的端口表)

二、镜像选型说明

Graphite 官方维护三种部署产物(来源:docker-graphite-statsd README,查询日期 2026-10-20):

方案产物适用
一体化镜像graphiteapp/graphite-statsd单机快速部署,一个服务包含全部组件(本文采用)
分组件安装pip 包 / 源码(graphite-web、carbon、whisper 各自独立)需要多机分拆、精细控制进程的大型部署
实验特性镜像内 GOCARBON=1(go-carbon 替换 carbon)、BRUBECK=1(brubeck 替换 statsd)特性评估,不建议生产

一体化镜像选择理由:官方出品(graphite-project 组织)、1.1.10-5 为该版本的最新稳定构建、Alpine 底座体积可控、内置 runit 与 healthcheck 所需工具,对单机部署与评估最友好。本镜像最新稳定 tag 为 1.1.10-5;latest 指向同一稳定线(2023-07-09 构建),master 为不稳定开发版,生产固定具体版本号。

三、前置条件

  1. 服务器已安装 Docker Engine 与 Compose 插件,验证:
docker --version

实测回显:

Docker version 29.8.1, build 4a63305
docker compose version

实测回显:

Docker Compose version v5.5.1
  1. 服务器可拉取 Docker Hub 镜像(内网环境请提前配置镜像加速或代理)。
  2. 规划端口未被占用,验证(本例 8128/8129/8132/8133):
ss -ltn | grep -E ':8128|:8129|:8132'

实测回显(无输出即空闲;若被占用请更换宿主端口,容器端口不变)。

四、部署步骤

4.1 创建部署目录

mkdir -p /opt/graphite-deploy/graphite/{conf,storage,statsd}
cd /opt/graphite-deploy

三个子目录分别对应镜像内的配置、whisper 数据、statsd 配置挂载点,首次启动为空目录时由镜像 entrypoint 自动初始化默认配置。

4.2 编写 docker-compose.yml

在 /opt/graphite-deploy 下创建 docker-compose.yml:

name: graphite-1.1.10-stack

services:
  graphite:
    image: graphiteapp/graphite-statsd:1.1.10-5
    container_name: graphite-1.1.10-web
    hostname: graphite-server
    restart: unless-stopped
    ports:
      - "8128:80"
      - "8129:2003"
      - "8132:2004"
      - "8133:8125/udp"
    environment:
      - GRAPHITE_TIME_ZONE=Asia/Shanghai
    volumes:
      - ./graphite/conf:/opt/graphite/conf
      - ./graphite/storage:/opt/graphite/storage
      - ./graphite/statsd:/opt/statsd/config
    networks:
      - graphite-net
    healthcheck:
      test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8080/ || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 6
      start_period: 60s

networks:
  graphite-net:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.57.0/24

关键项说明:

  • name: graphite-1.1.10-stack:显式声明 Compose 项目名,避免多套部署共用目录名导致互相覆盖;
  • container_name / hostname:固定实例名与主机名,carbon 内部指标路径默认使用主机名(carbon.agents.graphite-server-a.*),固定后指标名不漂移;
  • healthcheck:通过访问 8080(gunicorn 直连端口)判断 Web 服务是否就绪,Alpine 自带 busybox wget;
  • 网络 subnet:多套监控栈并存时显式指定网段,避免与既有 Docker 网络冲突;
  • 端口映射:宿主端口全部可自定义,容器内端口固定(见 4.4 端口表)。

4.3 启动并确认健康

docker compose up -d

实测回显:

[+] Running 2/2
 ✔ Network graphite-1.1.10-stack_graphite-net  Created
 ✔ Container graphite-1.1.10-web               Started

首次启动需要初始化配置与 Django 数据库,等待约 1 分钟后确认状态:

docker compose ps

实测回显:

NAME                  IMAGE                                  COMMAND         SERVICE   CREATED          STATUS                    PORTS
graphite-1.1.10-web   graphiteapp/graphite-statsd:1.1.10-5   "/entrypoint"   graphite   50 seconds ago   Up 50 seconds (healthy)   2013-2014/tcp, 2023-2024/tcp, 8080/tcp, 8125-8126/tcp, 0.0.0.0:8128->80/tcp, [::]:8128->80/tcp, 0.0.0.0:8129->2003/tcp, [::]:8129->2003/tcp, 0.0.0.0:8132->2004/tcp, [::]:8132->2004/tcp, 0.0.0.0:8133->8125/udp, [::]:8133->8125/udp

STATUS 出现 Up (healthy) 即健康检查通过。若长时间停留在 health: starting,查看启动日志:

docker compose logs graphite | tail -20

实测回显(节选,正常应出现各服务的 runit OK 行):

graphite-1.1.10-web  | graphite-web: OK
graphite-1.1.10-web  | carbon-cache: OK
graphite-1.1.10-web  | carbon-aggregator: OK
graphite-1.1.10-web  | statsd: OK
graphite-1.1.10-web  | nginx: OK

4.4 端口表

宿主端口(本例)容器端口服务协议
812880nginx(graphite-web 反向代理入口)TCP
81292003carbon-cache 明文行协议接收TCP
81322004carbon-cache pickle 批量接收TCP
81338125statsd 指标接收UDP
未映射8080graphite-web gunicorn 直连端口(healthcheck 用)TCP
未映射8126statsd 管理接口TCP
未映射2013/2014carbon-relay(默认未启用)TCP
未映射2023/2024carbon-aggregator(默认启用)TCP

4.5 验证 Web 服务

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8128/

实测回显:

200
curl -sS http://127.0.0.1:8128/ | grep -oE '<title>[^<]*</title>'

实测回显:

<title>Graphite Browser</title>

登录页验证(默认管理员账号 root,初始密码 root,首次登录后请立即在 /admin/password_change/ 修改):

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8128/account/login

实测回显:

200

浏览器访问 http://<服务器IP>:8128/ 进入 Graphite Browser 图表界面,/dashboard 进入仪表盘编辑器。

五、数据持久化说明

数据全部落在宿主三个 bind mount 目录,重启/重建服务不丢数据:

宿主目录容器路径内容
./graphite/conf/opt/graphite/confcarbon.conf、storage-schemas.conf 等 12 个配置文件(首次启动自动生成)
./graphite/storage/opt/graphite/storagewhisper 指标数据(whisper/)、Django 元数据库(graphite.db)、各服务 pid
./graphite/statsd/opt/statsd/configstatsd 的 udp.js/tcp.js 配置(空目录时用内置默认)

首次启动后确认宿主侧配置已生成:

ls /opt/graphite-deploy/graphite/conf/

实测回显:

aggregation-rules.conf  blacklist.conf  carbon.amqp.conf  carbon.conf
dashboard.conf  go-carbon.conf  graphTemplates.conf  relay-rules.conf
rewrite-rules.conf  storage-aggregation.conf  storage-schemas.conf  whitelist.conf

whisper 数据目录结构(指标路径映射为子目录层级):

find /opt/graphite-deploy/graphite/storage/whisper -name '*.wsp' | head -6

实测回显(碳服务自监控指标在启动后即产生):

/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/creates.wsp
/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/errors.wsp
/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/metricsReceived.wsp
/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/timings/create.wsp
/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/timings/updateOperation.wsp
/opt/graphite-deploy/graphite/storage/whisper/carbon/agents/graphite-server-a/updateOperations.wsp

六、环境变量表

镜像通过环境变量覆盖 carbon.conf / local_settings.py / statsd 配置(来源:docker-graphite-statsd README「Tunables」节,默认值为 README 原文),常用项:

环境变量默认值说明
GRAPHITE_TIME_ZONEEtc/UTCDjango 时区
GRAPHITE_ALLOWED_HOSTS*Django 允许的 Host
GRAPHITE_WSGI_PROCESSES4gunicorn worker 进程数
GRAPHITE_WSGI_THREADS1每 worker 线程数
GRAPHITE_WSGI_REQUEST_TIMEOUT65请求超时秒数
GRAPHITE_DEFAULT_CACHE_DURATION60查询结果缓存秒数
GRAPHITE_CARBONLINK_HOSTS127.0.0.1:7002carbonlink 缓存查询地址
GRAPHITE_UTF8_METRICSfalse允许 UTF-8 指标名(有性能代价)
CARBON_DISABLE_TAGSfalse置 1 关闭 carbon 的 TagDB
REDIS_TAGDBfalse置 1 用内置 Redis 存 TagDB
MEMCACHE_HOST未设配置后启用 Memcached 查询缓存
STATSD_INTERFACEudp置 tcp 让 statsd 监听 TCP 8125
RELAY未设置 1 启用 carbon-relay
COLLECTD未设置 1 启用内置 collectd 自监控
<服务名>_DISABLED未设置 1 关闭对应 runit 服务(如 CARBON_AGGREGATOR_DISABLED=1)

七、端到端验证:打点 → 查询曲线

7.1 向 carbon 2003 端口打点

明文行协议格式:<指标路径> <值> <UNIX时间戳>,用 nc 直接推送:

now=$(date +%s)
for i in 1 2 3 4 5 6; do
  t=$((now - (6 - i) * 10))
  echo "servers.web1.requests $((i * 10)) $t" | nc -w 2 127.0.0.1 8129
done

carbon-cache 先入内存缓存再刷盘,等待约 5 秒后可查询。

7.2 render API 查询数据

curl -sS 'http://127.0.0.1:8128/render?target=servers.web1.requests&from=-2min&format=json'

实测回显(打点 6 个,全为非空数据点):

[{"target": "servers.web1.requests", "tags": {"name": "servers.web1.requests"}, "datapoints": [[10.0, 1792471260], [20.0, 1792471270], [30.0, 1792471280], [40.0, 1792471290], [50.0, 1792471300], [60.0, 1792471310], [null, 1792471320], [null, 1792471330], [null, 1792471340], [null, 1792471350], [null, 1792471360]]}]

点已从 carbon-cache 写入 whisper 并被 render API 读回,写路径与读路径全部打通。

7.3 指标发现 API 验证

curl -sS 'http://127.0.0.1:8128/metrics/find?query=servers.*'

实测回显:

[{"text": "web1", "id": "servers.web1", "allowChildren": 1, "expandable": 1, "leaf": 0}, {"text": "web2", "id": "servers.web2", "allowChildren": 1, "expandable": 1, "leaf": 0}]
curl -sS 'http://127.0.0.1:8128/metrics/index.json' | python3 -c 'import json,sys; m=json.load(sys.stdin); print(len(m), "metrics"); print(m[0])'

实测回显:

125 metrics
carbon.agents.graphite-server-a.activeConnections

7.4 statsd UDP 打点验证

counter 类型报文 key:value|c,用 nc 推 UDP:

for i in 1 2 3 4 5; do
  echo -n "s7demo.pageview:$((i * 7))|c" | nc -w 1 -u 127.0.0.1 8133
done

statsd 每 10 秒 flush 一次(刷新周期由 /opt/statsd/config/udp.js 的 flushInterval 决定),等待后查询:

curl -sS 'http://127.0.0.1:8128/render?target=stats.s7demo.pageview&from=-5min&format=json'

实测回显(statsd 聚合出的速率值):

[{"target": "stats.s7demo.pageview", "datapoints": [[0.7, 1792471380], [9.8, 1792471390], [null, ...]}]

⚠️ 注意:statsd 的 flushInterval(默认 10 秒)必须不小于 storage-schemas.conf 中最高精度归档的间隔,否则聚合错位。默认 schema 10s:6h,... 与默认 10 秒 flush 恰好匹配。

7.5 Web UI 查看曲线

浏览器打开 http://<服务器IP>:8128/,左侧 Composer 的 Graphite Metrics 树中展开 servers → web1 → requests 点击即出现曲线;或直接访问:

http://<服务器IP>:8128/render?target=servers.web1.requests&from=-10min

返回 PNG 曲线图即验证完成。

八、等价 docker run 命令

与上述 compose 等价的单命令启动(官方 README 原始形态,按本文端口规划改写):

docker run -d \
  --name graphite-1.1.10-web \
  --restart=always \
  -p 8128:80 \
  -p 8129:2003 \
  -p 8132:2004 \
  -p 8133:8125/udp \
  -v /opt/graphite-deploy/graphite/conf:/opt/graphite/conf \
  -v /opt/graphite-deploy/graphite/storage:/opt/graphite/storage \
  -v /opt/graphite-deploy/graphite/statsd:/opt/statsd/config \
  -e GRAPHITE_TIME_ZONE=Asia/Shanghai \
  graphiteapp/graphite-statsd:1.1.10-5

九、常用运维命令

docker compose ps                 # 栈状态与健康检查
docker compose logs -f graphite   # 跟踪全部 runit 服务日志
docker compose stop               # 停栈(保留容器)
docker compose start              # 再启动
docker compose down               # 删容器与网络(数据在宿主 bind mount 不丢)
docker compose up -d              # 变更 compose 后重建

修改配置(conf 目录下任一文件,如 storage-schemas.conf)后,重启栈生效:

docker compose restart graphite

十、常见问题

Q1:栈一直 health: starting 或 unhealthy? healthcheck 访问的是容器内 8080 gunicorn 端口。进入容器排障:docker compose exec graphite wget -q -O- http://127.0.0.1:8080/,若报错查看 /var/log/graphite/exception.log;常见原因是宿主内存过小导致 gunicorn 被 OOM 杀,可用 GRAPHITE_WSGI_PROCESSES=2 降进程数。

Q2:打点成功但查询全为 null? carbon-cache 默认缓存刷盘有秒级延迟,打点后等 5–10 秒再查;仍为空则确认时间戳是 UNIX 秒且未写未来时间,并检查 storage-schemas.conf 是否保留了你打点的时间范围。

Q3:宿主端口冲突如何改? 只改 compose 中冒号左侧的宿主端口即可,容器内端口(80/2003/2004/8125)固定不动;UDP 8125 对应 statsd 埋点,漏映射会导致 stats.* 指标收不到。

Q4:忘记 Web 管理员密码? 默认账号 root/root;修改入口是 Web 界面 /admin/password_change/。遗忘后可删除 graphite/storage/graphite.db(Django 元数据库,不含指标数据)后重启栈重新初始化,同时重建管理员。

Q5:磁盘写满有什么表现? whisper 预分配文件写满失败时 carbon 日志出现 Disk I/O error,carbon.agents.*.errors 指标升高。whisper 文件是固定大小,磁盘不足主要发生在新建指标时(MAX_CREATES_PER_MINUTE 同时受 CPU 限制),扩容磁盘后 docker compose restart graphite 恢复。

十一、参考链接