最近在给公司的网络做监控割接,挑来挑去最后还是选了LibreNMS。原因很简单:它是我见过的开源网络监控系统里,功能最接近商业产品的那一类,自动发现、画拓扑、出图、告警一个不缺,而且用Docker Compose部署起来,真的就是一份yaml文件的事。这篇文章就把我这次搭建LibreNMS的完整过程、踩过的坑、以及最终稳定运行的配置方案都整理出来,给正在纠结怎么下手的朋友一个可以直接抄的作业。
我用Docker Compose跑LibreNMS这套组合,已经稳定运转了两三个月,管理着包括交换机、路由器、防火墙在内的四十多台设备,采集到的监控数据用来做带宽趋势分析、故障排查和容量规划,都非常顺手。无论你是刚接触网络监控的运维新人,还是想替换旧监控系统的老手,只要你手里有能跑Docker的机器,这篇文章里讲的东西就能直接落地。
1. 为什么选择LibreNMS,以及Docker Compose解决了什么问题
1.1 LibreNMS的核心能力与适用场景
先花一点时间说说LibreNMS到底是个什么级别的工具。它是一款基于PHP和MySQL的开源网络监控平台,走的是SNMP协议采集路线。简单说,只要网络设备支持SNMP,不管是Cisco、华为、H3C、Juniper、锐捷还是各种白牌交换机,LibreNMS基本都能自动发现、自动识别型号,然后开始采集CPU、内存、接口流量、温度这些关键指标,并生成图形报表。
它有几个让我觉得特别香的点。第一是自动发现能力很强,设备接入后它会自动扫描关联的邻居设备,还能自动识别常见的设备类型和接口状态;第二是出图漂亮又直观,接口流量图、CPU负载图都是rrdtool实时生成的,拿来做月度流量分析和带宽扩容依据非常方便;第三是告警规则灵活,可以基于采集数据自定义阈值,通过邮件、钉钉机器人、Slack等渠道推送。
适用场景也很明确——中小规模网络、混合品牌设备环境、需要快速上手的团队。如果你手底下只有几台设备,用不用监控系统都无所谓;但一旦设备数量上了两位数,没有一张总览图,出问题全靠人肉排查,效率就太低了。
1.2 Docker Compose部署相比传统方式强在哪
LibreNMS的官方安装文档其实也支持手动装,LNMP环境、PHP扩展、composer依赖、crontab定时任务,每一步都要自己来。我在测试环境里手动装过一次,光是配PHP-FPM和Nginx就折腾了小半天,更别提后续升级时的各种兼容性问题。
用Docker Compose部署,本质上就是把LibreNMS的Web服务、数据库、缓存这些组件装进各自的容器,再用一份yaml编排文件把它们串起来。这样做有几个非常现实的好处:
- 部署速度快:一条
docker compose up -d就完成了环境搭建,剩下的就是写配置和初始化,整个过程十几分钟。 - 环境隔离能力强:LibreNMS依赖的PHP版本、扩展、Nginx配置全部固化在镜像里,不会污染宿主机,也不会跟其他应用起冲突。
- 升级回滚方便:官方镜像发布新版本后,拉取新镜像重启容器就能完成升级,出现问题也能快速切回旧镜像。
- 迁移复制容易:整份compose文件加数据目录打包带走,到新机器上直接启动,监控数据都还在。
拿生活里的场景做个类比:手动部署就像自己从买面粉开始做一顿饭,Docker Compose就是给你一份带配料的半成品料理包,虽然最后菜的出品还得看厨艺,但前期的准备工作已经被大大压缩了。
2. 环境准备与Compose文件设计
2.1 宿主机要求与Docker环境安装
先交代一下我用的环境,方便大家对号入座。我部署在一台Ubuntu 22.04 LTS服务器上,配置是4核8G、120G SSD。实际跑下来,管理四十多台设备,每5分钟轮询一次,CPU占用率平时也就10%左右,内存占了大约2G,其中MySQL是吃内存的大头。如果你的设备数量在一百台以内,4核8G完全够用;超过两百台,建议升到8核16G,并考虑把MySQL单独放一台机器。
Docker和Compose的安装,不同系统的做法不太一样。Ubuntu和Debian系统比较省事,直接用官方源装就行:
# 安装Docker CE sudo apt update sudo apt install docker.io docker-compose-v2 sudo systemctl enable --now docker # 验证Compose是否可用 docker compose version如果你用的是CentOS、麒麟这类系统,默认仓库里往往没有docker-ce包,需要先添加对应的软件源再安装。有些内网环境连外部源都访问不了,那就只能先在有网的环境下载rpm包,再拿进去离线安装。这一步看着基础,但卡住的人真不少,后面问题排查部分我会专门说。
装好之后记得看一眼版本。Compose v2命令是docker compose(中间有空格),不是老版本的docker-compose(带横线),这两个命令的兼容性差别后面会细讲。
2.2 docker-compose.yml逐段拆解
这是我用的docker-compose.yml,直接贴出来,然后逐段解释为什么这么写。
services: db: image: mariadb:10.5 container_name: librenms_db restart: unless-stopped command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci environment: MYSQL_DATABASE: librenms MYSQL_USER: librenms MYSQL_PASSWORD: librenms_pass MYSQL_ROOT_PASSWORD: root_pass TZ: Asia/Shanghai volumes: - ./data/mysql:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 30s timeout: 10s retries: 5 redis: image: redis:6-alpine container_name: librenms_redis restart: unless-stopped command: - redis-server - --appendonly yes volumes: - ./data/redis:/data librenms: image: librenms/librenms:latest container_name: librenms restart: unless-stopped hostname: librenms depends_on: db: condition: service_healthy redis: condition: service_started ports: - "8000:80" environment: TZ: Asia/Shanghai DB_HOST: db DB_PORT: 3306 DB_NAME: librenms DB_USER: librenms DB_PASSWORD: librenms_pass REDIS_HOST: redis REDIS_PORT: 6379 volumes: - ./data/librenms:/data networks: default: name: librenms_net这里有几个设计上的考量值得展开说说。
数据库选MariaDB而不是MySQL。LibreNMS官方在文档里明确支持MariaDB,而且MariaDB 10.5在资源占用和稳定性上都表现不错,镜像体积也比MySQL小不少。实际操作中不需要额外安装PHP的MySQL驱动,容器里的LibreNMS连上就能用。
给db服务加了healthcheck。这是很多样例compose文件里最容易缺的东西。如果没有健康检查,LibreNMS容器可能在数据库还没初始化完成时就启动,导致连接失败然后反复重启。我用的是MariaDB镜像自带的healthcheck脚本,只有当数据库真正能连接时才把db标记为healthy。然后在LibreNMS的depends_on里配置condition: service_healthy,这样就能保证启动顺序正确,不会出现那种"日志刷屏却起不来"的尴尬。
数据全部挂载到宿主机。容器本身是无状态的,一旦删掉所有数据就没了。我把MySQL数据放在./data/mysql,LibreNMS的RRD文件、日志、配置放在./data/librenms,Redis的持久化数据放在./data/redis。这样不管容器怎么重建,数据都稳稳地在宿主机上。
Redis用了appendonly持久化。LibreNMS的告警队列和部分缓存都依赖Redis,虽然就算Redis丢几个数据也不致命,但开了持久化更稳妥,代价只是多占一点磁盘空间。
端口映射默认是8000:80,宿主机8000端口指到容器里的80端口。如果你80端口空着,也可以直接改80:80,访问的时候连端口都不用带。不过我还是建议用8000,避免跟其他Web服务冲突,也方便用Nginx反代做域名绑定。
2.3 数据持久化与目录规划
目录规划这件事,看着不起眼,但出问题的时候特别能体现价值。我的推荐布局是项目目录下统一放一个data子目录,里面按组件分文件夹:
/opt/librenms/ ├── docker-compose.yml ├── .env └── data/ ├── mysql/ ├── redis/ └── librenms/ ├── config.d/ ├── logs/ └── rrd/把全部数据放在项目目录里,好处是以后备份、迁移都简单。备份的时候只需要打包整个项目目录,再配合mysqldump或者直接复制mysql目录就行。恢复的时候把目录解压回去,docker compose up -d,一切照旧。
还有个容易被忽略的坑:宿主机目录权限问题。LibreNMS容器内的用户ID和宿主机用户不一样,如果./data/librenms目录权限不对,容器启动后可能写入失败,表现为"页面能打开但图表一直出不来"或者"RRD文件无法创建"。遇到这种情况,进容器看一眼日志,多半是permission denied。解决办法很简单:
# 进入项目目录后执行 chown -R 1000:1000 ./data/librenms不同镜像内部的用户ID可能不同,LibreNMS官方镜像用的是1000,如果你发现还是不对,进容器里执行id命令看看到底用的什么UID,再回宿主机对应调整就行。
3. 完整部署实操记录
3.1 一键拉起全部容器
环境准备好、compose文件写好后,正式部署就很短平快了。进入项目目录执行:
docker compose up -d第一次启动需要拉取镜像,mariaDB、redis、librenms三个镜像加起来大概1.3G左右,取决于网速,可能要等几分钟。网络不佳的时候耐心点,或者提前配置好镜像加速,别半路去倒杯水回来发现curl超时了。
拉取完成后,用下面几个命令确认状态:
docker compose ps docker compose logs -f librenms如果一切正常,ps的输出里三个服务应该都是Up状态,logs里能看到Nginx和PHP-FPM正常启动的日志。这时候浏览器访问http://服务器IP:8000,就能看到LibreNMS的安装引导页面了。
3.2 Web安装向导与初始配置
安装页面的操作很直观,但有几个细节我建议你留意。
页面第一步会做环境检查,列出PHP扩展、目录权限、依赖包的状态。官方镜像已经把该装的都装好了,这里基本是全绿的。真正需要填的是数据库连接信息,按照compose里设置的值填写:
数据库地址: db 数据库端口: 3306 数据库名: librenms 用户名: librenms 密码: librenms_pass注意数据库地址填的是**服务名db**而不是IP地址,因为LibreNMS容器和DB容器在同一个Docker网络里,通过服务名就能互相访问。填了IP反而可能连不上,因为Docker网段跟宿主机网段本来就不是一回事。
数据库检查通过后,会进入创建管理员的步骤,设置用户名、邮箱和密码。这里我强烈建议密码别用你平时的弱口令,LibreNMS后台能做的事情太多了,改交换机SNMP字符串、导出配置,一旦被别人拿到,等于直接接管了你的监控系统。
安装完成后,页面会提示你删除或重命名install.php文件。在Docker环境下的操作是进容器里删:
docker compose exec librenms rm -f /opt/librenms/install.php如果留着这个文件,每次访问都会弹安装向导,还有被恶意重新初始化的风险。这一步务必做。
3.3 登录后台的第一件小事:验证轮询与发现任务
登录后台之后,先别急着加设备。LibreNMS的日常数据采集依赖于定时任务,一个负责发现设备、一个负责轮询采集数据。Docker镜像内部已经把这两个任务调度好了,也不需要额外配置crontab。但你应该主动验证一下任务是否正常执行。
进容器手动触发一次发现和轮询:
docker compose exec librenms ./lnms poll:discovery看到类似Discovered devices: 0或者没有报错信息,说明调度正常。如果这里报错,多半是数据库连接或权限问题,这在后面排查部分还会讲到。
此时可以顺手把时区确认一下。compose里已经设置了TZ=Asia/Shanghai,但LibreNMS后台还有一个时区选项,位置在"设置"里的"区域设置"页面,改成Asia/Shanghai,不然图表时间跟北京时间差8小时,看起来非常别扭。
4. 添加真实设备:SNMP接入与收图
4.1 网络设备侧的SNMP配置
监控一切的基础是设备愿意把数据交出来,这就要在设备上开SNMP。以最常见的v2c协议为例:设置一个只读的community字符串,然后限定允许访问的源IP,只允许监控服务器的地址来采集。
思科交换机上的配置很简单:
snmp-server community public RO snmp-server location Beijing-IDC snmp-server contact netops@example.com华为设备稍微有一点差别:
snmp-agent snmp-agent community read cipher public snmp-agent sys-info location Beijing-IDC snmp-agent sys-info contact netops@example.com这里的public只是示意,生产环境绝对不要用public这种默认字符串。我习惯用一组随机生成的字符串作为community,只配成只读权限,然后在防火墙上限制只有监控服务器能访问设备的UDP 161端口。
设备配好之后,先在监控服务器上测试一下能不能取到数据。用snmpwalk确认:
snmpwalk -v 2c -c 你的字符串 192.168.1.100 system如果返回设备名称、描述、运行时间等等一堆信息,说明SNMP通信正常。如果返回超时,先检查设备到监控服务器的网络通不通,再检查防火墙的UDP 161端口有没有放行。
4.2 在LibreNMS里添加设备
设备SNMP配好,验证通了之后,就可以加入LibreNMS了。后台导航里找到"设备"->"添加设备",填写下面几项:
- 主机名:IP地址或能解析的域名,我习惯直接用IP。
- SNMP版本:选v2c。
- Community字符串:填设备上配置的那个。
- 端口的SNMP:默认161就行。
填完之后提交,LibreNMS会自动向设备发起SNMP查询,能通的话设备马上出现在设备列表里。紧接着后台会自动开始新设备的数据发现,几分钟后就能在设备的"概览"页面看到CPU、内存、接口等信息。
如果设备型号比较新,自动识别偶尔会失败。设备页面上显示乱码或者信息不全,可以手动更新一下硬件信息,在设备页选"编辑设备",手动修正厂商、型号和操作系统版本,LibreNMS会针对这些信息调整采集项。
还有一种情况是多台设备批量接入。系统支持在Web界面里一个个加,也可以用命令行批量加,我一般在初始化阶段用命令一次性把几十台加进去:
docker compose exec librenms ./lnms device:add --hostname 192.168.1.101 --community public --v2c4.3 告警通知与日常维护建议
设备能出图之后,别急着松口气,告警才是监控系统的灵魂。LibreNMS默认带了一批告警规则,比如设备宕机、接口状态变化、CPU使用率过高,但默认规则不一定符合你的预期,你需要到"告警规则"页面里逐个检查,调整阈值。
我自己的习惯是配置三类核心告警:设备down、接口up/down变化、WAN口带宽利用率超过80%。前两个是故障排查刚需,带宽利用率阈值是容量规划的重要参考。通知渠道我选了邮件加钉钉机器人,钉钉机器人通过自定义webhook就能接入,网上很多现成脚本,LibreNMS也可以直接用"传输方式"里的webhook模板,把webhook URL填进去就行。
日常维护方面,有几点经验供你参考。一是定期检查磁盘空间,RRD文件虽然不大,但设备多了累积起来很可观,我一般用grafana那一套可视化之前,先确保宿主机磁盘有30%以上的余量。二是定期更新容器镜像,官方镜像基本每月都有更新,跟着版本走能修掉不少安全漏洞。三是日志别忽视,./data/librenms/logs下的日志是排查问题的一手线索。
5. 常见问题与排查实录
5.1 docker compose命令不识别怎么办
这个真是太常见了,搜索热度一直居高不下:执行docker compose up -d,结果报docker: unknown command: docker compose。这句话的意思不是说Docker没装,而是你的Docker里缺少Compose插件。
解决办法取决于你的Docker版本。Docker 20.10以上的版本自带插件体系,装一下插件就行:
apt install docker-compose-v2老一点的环境装的是独立的docker-compose命令,那就别用空格写法:
docker-compose up -d还有一个诡异的场景:Docker装了,compose插件也装了,但报一样的错。多半是PATH环境变量问题,Docker插件目录没被识别。可以检查一下/usr/libexec/docker/cli-plugins或者/usr/lib/docker/cli-plugins下有没有docker-compose这个文件。没有的话就手动放一个。
5.2 SNMP采集不到数据
设备加进去了,但页面上一直是空的,图也没数据。这个问题我要单独拎出来说,因为它80%是设备侧的配置问题。
先手动重新发现一次,看有没有报错:
docker compose exec librenms ./lnms poll:device --device-id 1 --debug加了--debug参数之后,会输出很详细的采集日志。常见的结果有两种。
一种是timeout,说明设备根本没回应SNMP请求。这时候回到设备侧排查,snmpwalk能不能通,防火墙UDP 161没有放行,ACL是否限制了对端IP。我之前踩过一次,明明UDP放行了还是不通,最后发现是设备上的ACL把监控服务器地址挡了,日志不看根本发现不了。
另一种是返回noSuchName之类的错误,说明community字符串对不上,或者设备上这个指标不在采集范围。检查一下设备上的配置和LibreNMS里的字符串是否一字不差。
5.3 Web界面白屏或502
访问页面直接502 Bad Gateway,多半是LibreNMS容器里的PHP-FPM挂了,或者是数据库连接异常导致PHP请求执行时间过长。先看容器状态和日志:
docker compose ps docker compose logs --tail 50 librenms如果是容器反复重启,基本是环境变量配置错了,重点检查DB_HOST、DB_PASSWORD是否和数据库一致。如果容器正常运行但页面502,进容器手动重启PHP-FPM进程就好:
docker compose exec librenms /etc/init.d/php-fpm restart还有一种情况是数据库磁盘满了,MySQL拒绝写入,页面也会白屏。用df -h看一下宿主机磁盘,一旦超过90%,优先清理日志和旧的RRD文件。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| docker compose命令不存在 | Compose插件未安装 | 安装docker-compose-v2插件 |
| 容器反复重启 | 数据库未就绪或密码错误 | 检查healthcheck和DB_PASSWORD配置 |
| 设备无数据 | 设备SNMP未开启 | snmpwalk验证,检查UDP 161端口 |
| 页面502 | PHP-FPM异常 | 重启PHP-FPM,查看容器日志 |
| 图表不出图 | RRD目录权限错误 | chown -R 1000:1000数据目录 |
| 告警不推送 | 通知渠道配置错误 | 在传输方式里点测试按钮验证 |
| 时区显示偏移 | PHP或软件时区未设置 | 在后台设置里改Asia/Shanghai |
6. 最后再分享一点我的实际体会
监控系统的建设是个持续迭代的过程,LibreNMS最让我满意的一点是它不需要你刻意经营,设备加进去之后数据就源源不断产出来,时间越久,历史数据越有参考价值。等你用流量图说话去说服领导扩容宽带、用CPU曲线证明某台设备该换了的时候,你就会觉得当初花几个小时部署它值回票了。
如果后续你的监控规模继续变大,还可以把它和Grafana对接起来,把LibreNMS里的数据做成更炫酷的大屏,或者让LibreNMS配合Oxidized做配置备份,效果都很顶。先把这套基础环境跑稳,后续扩展就是水到渠成的事。我已经跑了一段时间,整体非常省心,你也完全可以。