Munin 2.0.57 部署指南
Munin 2.0.57 Docker Compose 部署指南:自建双角色镜像(master/node 环境变量分发)、compose 编排 1 master + 2 node、显式网段 10.89.60.0/24、RRD 数据持久化、配置挂载与节点 ACL 自动放行,含 pid 目录与 CGI::Fast 缺失等排障实录,全部命令与回显实测。
Munin 2.0.57 部署指南
目标:用 Docker Compose 一键部署「1 个 Munin master + 2 个被监控 node」的完整监控栈,覆盖镜像构建选型、端口与网段规划、数据持久化、配置挂载、节点 ACL 自动放行与日常运维命令。全文在 Docker Compose v5.5.1 + Ubuntu 22.04 基础镜像环境实测通过,Web 界面、静态/CGI 出图与多节点采集均逐条验证。
一、环境信息
- 宿主操作系统:Ubuntu 22.04(x86_64)
- Docker 与 Compose:Docker Engine + Docker Compose v5.5.1(
docker compose version实测) - Munin 版本:2.0.57-1ubuntu2(镜像内基于 ubuntu:22.04 经 apt 安装,
munin version 2.0.57实测) - 栈内拓扑:munin-master(采集 + Web 出图,映射宿主 8131→80)+ munin-node2 + munin-node3
- 自定义网络:munin-net(bridge,显式子网 10.89.60.0/24,固定各节点 IPv4)
- 持久化卷:munin-db(RRD 数据)、munin-www(HTML/图形输出)、munin-logs(日志)
- 访问入口:宿主机
http://<宿主IP>:8131/munin/
二、镜像选型说明
Munin 官方不发布容器镜像,Docker Hub 上第三方镜像(如社区个人维护的 munin 镜像)版本陈旧、配置不可控。本方案选择自建镜像:以 ubuntu:22.04 为基础,apt 安装发行版仓库的 munin 全家桶(2.0.57)+ apache2,单一镜像通过环境变量区分 master/node 双角色——master 角色跑「cron 采集 + Apache 出图」,node 角色只跑 munin-node 前台。选型对比:
| 方案 | 版本可控性 | 维护成本 | 适用 |
|---|---|---|---|
| 自建镜像(本文) | 锁定 Ubuntu 22.04 仓库版 2.0.57,可升级 2.0.75/76 | 自己维护 Dockerfile | 生产推荐 |
| 第三方个人镜像 | 版本不明、多为 2.0.x 老包 | 低但不可控 | 快速体验 |
| 官方镜像 | Munin 官方不发布 | — | 不存在 |
镜像构建文件 Dockerfile(与 compose 文件同目录):
# Munin 2.0.57 (Ubuntu 22.04) master/node 双角色镜像
# 构建后由 compose 以不同 command/环境变量区分 master / node 角色
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
munin munin-node munin-plugins-extra apache2 cron tzdata curl telnet \
libwww-perl libcache-cache-perl libcgi-fast-perl && \
rm -rf /var/lib/apt/lists/*
# master 角色默认站点配置(静态 HTML + CGI 出图)
COPY munin-apache.conf /etc/apache2/conf-available/munin.conf
RUN a2enconf munin && a2enmod cgid && \
chown -R munin:www-data /var/log/munin && chmod -R g+rwX /var/log/munin && \
mkdir -p /var/log/munin/cgi && chown -R www-data:adm /var/log/munin/cgi && \
touch /var/log/munin/munin-cgi-graph.log /var/log/munin/munin-cgi-html.log && \
chown www-data:www-data /var/log/munin/munin-cgi-graph.log /var/log/munin/munin-cgi-html.log
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 80 4949
ENTRYPOINT ["/entrypoint.sh"]
Apache 站点片段 munin-apache.conf(静态 HTML + CGI 双通道,与裸机安装一致):
Alias /munin /var/cache/munin/www
<Directory /var/cache/munin/www>
Require all granted
Options FollowSymLinks SymLinksIfOwnerMatch
AddDefaultCharset UTF-8
</Directory>
ScriptAlias /munin-cgi/munin-cgi-graph /usr/lib/munin/cgi/munin-cgi-graph
<Location /munin-cgi/munin-cgi-graph>
Require all granted
Options +ExecCGI
</Location>
ScriptAlias /munin-cgi/munin-cgi-html /usr/lib/munin/cgi/munin-cgi-html
<Location /munin-cgi/munin-cgi-html>
Require all granted
Options +ExecCGI
</Location>
入口脚本 entrypoint.sh(角色分发 + node 端 ACL 自动放行):
#!/bin/bash
# 按环境变量 MUNIN_ROLE 决定角色:master=采集+Web 出图,node=仅被采集端
ROLE="${MUNIN_ROLE:-master}"
# 被采集端:放行 master 网段(cidr_allow 取自环境变量,逗号分隔多个网段)
if [ -n "$MUNIN_NODE_CIDR_ALLOW" ]; then
for net in $(echo "$MUNIN_NODE_CIDR_ALLOW" | tr ',' ' '); do
grep -q "cidr_allow $net" /etc/munin/munin-node.conf || echo "cidr_allow $net" >> /etc/munin/munin-node.conf
done
fi
# Net::Server 需要 pid 文件目录(systemd 场景由 RuntimeDirectory 提供,前台运行须自建)
mkdir -p /var/run/munin && chown munin:munin /var/run/munin
if [ "$ROLE" = "node" ]; then
exec /usr/sbin/munin-node --foreground
fi
# master 角色:cron 周期采集 + apache 前台出图
service cron start >/dev/null 2>&1
/usr/sbin/munin-node --foreground &
apache2ctl -DFOREGROUND &
wait -n
⚠️ 注意:两处来自实测的排障点已固化在构建文件中——其一,
apt --no-install-recommends会漏掉推荐依赖libcgi-fast-perl,CGI 出图将报Can't locate CGI/Fast.pm in @INC(详见第十一章 FAQ 2),必须显式列入安装清单;其二,前台运行 munin-node 前必须自建/var/run/munin,否则报Couldn't open pid file ... No such file or directory(FAQ 1)。
三、前置条件
- 宿主机已安装 Docker 与 Docker Compose v2+:
docker compose version
实测回显:
Docker Compose version v5.5.1
- 端口与网段规划:宿主 Web 端口选 8131(确认空闲);容器网段选 10.89.60.0/24(确认不与既有网络冲突):
ss -ltn | grep 8131 || echo "8131 空闲"
docker network ls | grep -c munin || echo "无同名网络"
实测回显:
8131 空闲
无同名网络
- 项目目录就绪:以下 5 个文件置于同一目录(如
/opt/munin-compose/):Dockerfile、munin-apache.conf、entrypoint.sh、munin.conf、docker-compose.yml。
四、部署步骤
4.1 编写 compose 文件
docker-compose.yml(name: 显式指定项目名,避免与同机其他 compose 项目因目录同名冲突;网络显式 --subnet 固定网段):
name: munin-2-0-57-stack
services:
munin-master:
build:
context: .
dockerfile: Dockerfile
image: munin-2.0.57-ubuntu22:v1
container_name: munin-master
hostname: munin-master1
ports:
- "8131:80"
environment:
MUNIN_ROLE: master
volumes:
- ./munin.conf:/etc/munin/munin.conf:ro
- munin-db:/var/lib/munin
- munin-www:/var/cache/munin/www
- munin-logs:/var/log/munin
networks:
munin-net:
ipv4_address: 10.89.60.10
restart: unless-stopped
munin-node2:
image: munin-2.0.57-ubuntu22:v1
container_name: munin-node2
hostname: node2
environment:
MUNIN_ROLE: node
MUNIN_NODE_CIDR_ALLOW: 10.89.60.0/24
networks:
munin-net:
ipv4_address: 10.89.60.11
restart: unless-stopped
munin-node3:
image: munin-2.0.57-ubuntu22:v1
container_name: munin-node3
hostname: node3
environment:
MUNIN_ROLE: node
MUNIN_NODE_CIDR_ALLOW: 10.89.60.0/24
networks:
munin-net:
ipv4_address: 10.89.60.12
restart: unless-stopped
volumes:
munin-db:
munin-www:
munin-logs:
networks:
munin-net:
driver: bridge
ipam:
config:
- subnet: 10.89.60.0/24
master 挂载的主配置 munin.conf(把两个 node 纳入采集范围):
# Munin master 主配置(挂载进容器覆盖默认值)
dbdir /var/lib/munin
htmldir /var/cache/munin/www
logdir /var/log/munin
rundir /var/run/munin
# 首轮采集完成后以 CGI 动态出图;static 首轮仍由 munin-cron 生成
tmpldir /etc/munin/templates
staticdir /etc/munin/static
# 分布式轮询并发度(节点多于 5 台时建议调大)
max_processes 4
# 本机(master 自身也作为被监控节点)
[munin-master1]
address 127.0.0.1
use_node_name yes
[node2]
address 10.89.60.11
use_node_name yes
[node3]
address 10.89.60.12
use_node_name yes
配置要点逐项说明:dbdir/htmldir/logdir/rundir 四目录分别对应三个命名卷与容器内运行目录;[munin-master1] address 127.0.0.1 让 master 顺带监控自身(容器内 munin-node 由 entrypoint 拉起);[node2]/[node3] 用固定 IPv4 寻址,节点扩缩只增删段落;max_processes 控制并行轮询 worker 数。
4.2 一键构建并启动
docker compose up -d --build
实测回显(输出节选,实测末段):
Container munin-node3 Starting
Container munin-master Starting
Container munin-node3 Started
Container munin-node2 Started
Container munin-master Started
确认三服务状态:
docker compose ps --format 'table {{.Name}}\t{{.Status}}'
实测回显:
NAME STATUS
munin-master Up 14 seconds
munin-node2 Up 14 seconds
munin-node3 Up 14 seconds
4.3 触发首轮采集并验证
首轮数据落盘(进入 master 手动跑一次 munin-cron,免去等 5 分钟 cron 周期):
docker compose exec munin-master su - munin --shell /bin/bash -c "/usr/bin/munin-cron"
docker compose exec munin-master grep "Munin-update finished for node" /var/log/munin/munin-update.log | tail -3
实测回显:
2026/10/19 22:58:14 [INFO]: Munin-update finished for node node3;node3 (3.30 sec)
2026/10/19 22:58:14 [INFO]: Munin-update finished for node node2;node2 (3.30 sec)
2026/10/19 22:58:14 [INFO]: Munin-update finished for node munin-master1;munin-master1 (3.34 sec)
宿主机验证 Web 三连(首页 / node2 页面 / 趋势图):
curl -s -o /dev/null -w "host-html:%{http_code}\n" http://127.0.0.1:8131/munin/
curl -s -o /dev/null -w "host-node2:%{http_code}\n" http://127.0.0.1:8131/munin/node2/node2/
curl -s -o /dev/null -w "host-png:%{http_code} size:%{size_download}\n" http://127.0.0.1:8131/munin/node2/node2/load-day.png
实测回显:
host-html:200
host-node2:200
host-png:200 size:13490
CGI 动态出图验证(容器内):
docker compose exec munin-master curl -s -o /dev/null -w "cgi:%{http_code} type:%{content_type} size:%{size_download}\n" http://127.0.0.1/munin-cgi/munin-cgi-graph/node2/node2/load-day.png
实测回显:
cgi:200 type:image/png size:13273
浏览器访问 http://<宿主IP>:8131/munin/ 应看到 munin-master1、node2、node3 三个分组的完整趋势页。部署成功判据:三个服务 Up、update 日志三节点全 finished、宿主 8131 三连 200。
五、数据持久化说明
| 卷名 | 容器内路径 | 内容 | 丢失影响 |
|---|---|---|---|
| munin-2-0-57-stack_munin-db | /var/lib/munin | RRD 文件 + datafile 索引 + limits 状态 | 历史趋势数据丢失,需重跑采集从零积累 |
| munin-2-0-57-stack_munin-www | /var/cache/munin/www | 静态 HTML/PNG 产物 | 可再生(下一轮 munin-cron 重建) |
| munin-2-0-57-stack_munin-logs | /var/log/munin | 各组件日志 | 可再生 |
验证持久化(实测):docker compose down 后 docker compose up -d,RRD 数据保留、Web 页面无需首轮等待即有历史数据;down -v 才会连卷一起删除。
RRD 文件查看(每指标字段一个文件,四档 RRA 环形存储,尺寸固定):
docker compose exec munin-master ls /var/lib/munin/node3/ | head -3
实测回显:
node3-cpu-guest-d.rrd
node3-cpu-idle-d.rrd
node3-cpu-iowait-d.rrd
💡 说明:RRDtool(Round-Robin Database)是 Munin 的底层时序存储,同类存储引擎对比——
存储引擎 特点 适用 RRDtool 固定尺寸环形文件、自动降采样、零数据库运维 Munin/Cacti 类主机趋势监控 MySQL/PG 历史表 查询灵活但需容量运维 Zabbix 类平台化监控 Prometheus TSDB 标签索引、高基数、压缩列存 云原生指标体系 Munin 采用 RRDtool 的取舍是磁盘占用恒定、无数据库依赖;代价是不支持任意窗口灵活查询。本方案实际采用 RRDtool(Munin 内建)。
六、环境变量表
| 变量 | 默认值 | 作用 | 取值示例 |
|---|---|---|---|
| MUNIN_ROLE | master | 服务角色:master=采集+Web,node=仅被采集端 | master / node |
| MUNIN_NODE_CIDR_ALLOW | 空 | node 角色:向 /etc/munin/munin-node.conf 追加 cidr_allow 网段,放行 master 来源;逗号分隔可多段 | 10.89.60.0/24 |
| TZ | UTC | 时区(影响图形横轴与日志时间戳) | Asia/Shanghai |
七、配置参数说明
master 核心配置即挂载的 munin.conf(4.1 节全文),关键参数:
dbdir / htmldir / logdir / rundir:四类目录,与 volumes 一一对应,改动会破坏与 compose 挂载的对应关系,保持默认;max_processes 4:并行轮询 worker 数。实测 3 节点轮询每轮约 3.3 秒;节点规模 50+ 时建议按 CPU 核数调到 8~16;tmpldir / staticdir:页面模板与静态资源位置,个性化界面时挂载覆盖;- host 段
[名字] address <IP> use_node_name yes:节点纳管声明,名字即页面分组层级。
node 端配置由 entrypoint 自动追加 cidr_allow,手工等价形态是在 /etc/munin/munin-node.conf 中写入:
cidr_allow 10.89.60.0/24
7.1 插件增补(node 容器内实测)
node 角色容器内用 munin-node-configure 启用更多插件(以启用 apache 插件族为例):
docker compose exec munin-node2 bash -c "apt-get update -qq && apt-get install -y -qq libwww-perl >/dev/null 2>&1; munin-node-configure --shell 2>/dev/null | grep 'ln -s' | bash; kill 1" 2>/dev/null; docker compose restart munin-node2
⚠️ 注意:容器内 node 进程以 PID 1 前台运行,装完依赖后
restart重新拉起才会重新探测插件;验证方式与裸机一致(munin-run apache_accesses输出accesses80.value <n>)。
八、配置文件挂载
| 宿主文件 | 挂载点 | 读写 | 说明 |
|---|---|---|---|
| ./munin.conf | /etc/munin/munin.conf | ro | master 主配置,改后 docker compose restart munin-master 生效 |
| ./munin-apache.conf | 构建期 COPY /etc/apache2/conf-available/munin.conf | 构建期 | 站点配置,改动需 docker compose up -d --build |
| ./entrypoint.sh | 构建期 COPY /entrypoint.sh | 构建期 | 角色分发逻辑 |
节点容器内的 /etc/munin/munin-node.conf 未挂载,由镜像默认值 + entrypoint 追加 cidr_allow 生成;需深度定制 node 端配置时,可仿照 master 把本地文件以 :ro 挂进对应 node 服务。
九、等价 docker run
不使用 Compose 时,等价的分步启动命令(同一镜像、同一网络):
docker network create --driver bridge --subnet 10.89.60.0/24 munin-net
docker build -t munin-2.0.57-ubuntu22:v1 /opt/munin-compose/
docker run -d --name munin-master --hostname munin-master1 \
-p 8131:80 \
-e MUNIN_ROLE=master \
-v /opt/munin-compose/munin.conf:/etc/munin/munin.conf:ro \
munin-2.0.57-ubuntu22:v1
docker run -d --name munin-node2 --hostname node2 \
-e MUNIN_ROLE=node -e MUNIN_NODE_CIDR_ALLOW=10.89.60.0/24 \
--network munin-net munin-2.0.57-ubuntu22:v1
⚠️ 注意:等价命令中 master 未挂卷、node2 未显式指定网络地址,仅用于理解 compose 语义;生产按第四章 compose 配置为准。
十、常用运维命令
docker compose ps # 栈内服务状态
docker compose logs munin-master # master 日志(cron/apache 输出)
docker compose exec munin-master bash # 进入 master 排障
docker compose exec munin-master su - munin --shell /bin/bash -c "/usr/bin/munin-cron" # 手动触发一轮采集
docker compose restart munin-node2 # 重启单个节点(改插件/配置后)
docker compose up -d --build # 改 Dockerfile/挂载文件后重建
docker compose down # 停栈保留数据卷
docker compose down -v # 停栈并删除数据卷(历史数据清零,慎用)
实测示例(telnet 协议抽查 node2 指标):
docker compose exec munin-node2 sh -c '(echo nodes; sleep 1; echo quit) | timeout 5 telnet 127.0.0.1 4949'
实测回显:
node2
.
💡 说明:
nodes返回该 node 上报的主机名,行首的.是协议结束符;node 角色容器docker compose logs通常为空——munin-node 的连接日志写在容器内/var/log/munin/munin-node.log,用docker compose exec munin-node2 tail /var/log/munin/munin-node.log查看。
十一、常见问题(FAQ)
Q1:node 容器反复重启,日志报 Couldn't open pid file "/var/run/munin/munin-node.pid" [No such file or directory]?
实测定位:Net::Server 写 pid 前要求 /var/run/munin 存在;systemd 场景由单元文件的 RuntimeDirectory 自动创建,容器前台运行无人创建。entrypoint 中 mkdir -p /var/run/munin 已固化修复;自建镜像漏掉此行必现该故障。
Q2:CGI 出图 500,Apache 错误日志 Can't locate CGI/Fast.pm in @INC ... at /usr/lib/munin/cgi/munin-cgi-graph line 36?
实测定位:Dockerfile 用了 --no-install-recommends,推荐依赖 libcgi-fast-perl(提供 CGI::Fast)未装。修复:依赖清单显式加 libcgi-fast-perl 后 docker compose up -d --build;静态出图(munin-cron 预渲染)不受此影响。
Q3:master 采不到 node,update 日志出现 No old data available for failed worker node2;node2?
实测定位:node 端 ACL 拒绝 master 来源(/var/log/munin/munin-node.log 出现 Denying connection from: ::ffff:10.89.60.10)。compose 已通过 MUNIN_NODE_CIDR_ALLOW=10.89.60.0/24 自动放行;自建配置漏掉 cidr_allow 即复现。修复后 docker compose restart munin-node2。
Q4:页面 200 但图形 404?
首轮 munin-cron 未跑或 URL 路径层级写错。容器内路径为 <htmldir>/<组名>/<主机名>/<插件名>-<日|周|月|年>.png,如 node2 的负载日图为 /munin/node2/node2/load-day.png(组名与主机名同名导致出现两层 node2);先跑 4.3 的首轮采集再核对 URL。
Q5:节点改了 IP 或加了节点怎么扩容?
三步:compose 文件复制一个 node 服务段(改 container_name/hostname/ipv4_address)→ munin.conf 追加对应 host 段 → docker compose up -d + 首轮采集。IPv4 固定在 10.89.60.0/24 内即可,无需动 ACL(网段已放行)。
Q6:想升级 Munin 到 2.0.75/2.0.76?
镜像 FROM 换 ubuntu:24.04(仓库 munin 2.0.75)或 ubuntu:25.10(2.0.76),tag 名与 compose image: 同步更新后重建;RRD 卷可跨版本复用(RRD 格式向下兼容),升级前建议 down 后对卷做备份(见十、运维命令)。
十二、参考链接
- Munin 官方文档(2.0 系列):https://guide.munin-monitoring.org/en/stable-2.0/
- 上游源码与 Releases:https://github.com/munin-monitoring/munin
- Docker Compose 官方文档:https://docs.docker.com/compose/
- RRDtool 官网:https://oss.oetiker.ch/rrdtool/
- 本专栏同族文档:《Ubuntu 22.04 安装 Munin 2.0.57 指南》(裸机安装与本篇 compose 部署互为替代方案)、《Munin 2.0.57 常用 CLI 命令与工具详解》