☰
Zabbix 7.4 Docker Compose 容器化部署实践与避坑指南
2026/10/21 4:39:37 网站建设 项目流程

1. 先想明白:Zabbix 7.4 上 Docker 到底图什么

先说结论:如果你手头有一台装好 Docker 引擎的 Linux 服务器,Zabbix 7.4 从零到看到第一张监控图表,大概只需要一顿饭的功夫。我最近刚把内部一套系统的监控搭完,从镜像选择、Compose 编排、数据库初始化到首台主机上线,整个链路重新走了一遍,把踩过的坑和可以直接照抄的操作都整理在下面。

很多刚接触 Zabbix 的朋友第一反应是"这东西重":要装数据库、装 Web 服务端、调一堆 PHP 参数,光依赖就能把人劝退。早期我用 rpm 包和源码编译装过 5.x 版本,印象最深的是依赖地狱——系统自带的 PHP 版本不对,就得手动换源或者从第三方仓库装,你永远猜不到下一个缺的包是什么。用 Docker 之后,环境层面的问题基本被官方镜像消化掉了:镜像里已经把 Nginx、PHP-FPM、时区组件按官方推荐配置调好,你要做的只是关心业务参数。

Zabbix 7.4 这个版本,界面比老版本清爽不少,模板中心和告警配置的逻辑也更顺。对中小规模监控(几十台服务器、几百个网络设备)来说,它的功能覆盖和上手成本都非常合适。当然,Docker 化不等于免维护。Zabbix 本质是"数据库 + 服务端 + Web + Agent"四件套,容器编排只是把复杂度收敛到一个 Compose 文件里,底层数据库性能、数据备份这些功课一样不能少。

1.1 容器化带来的真实收益

第一是可复现。整个部署收敛成一个 docker-compose.yml,团队里任何人拿着这个文件都能还原出一模一样的环境,不用再维护十页纸的安装文档。我见过不少团队因为环境差异导致"在我机器上明明能跑"这类事故,容器化之后这类问题基本绝迹。

第二是升级成本低。老版本升 Zabbix 要停服、备份、跑迁移脚本,容器化之后变成"备份数据 → pull 新镜像 → up -d"三步,剩下的 schema 迁移由服务端镜像启动时自动完成,省心很多。

第三是隔离干净。监控系统占用的端口、依赖的库版本都被封在容器里,跟业务系统互不干扰。想卸载的话,把容器和数据目录删掉就完事,不会在系统里留一堆残留文件。

1.2 哪些场景我不建议你用 Docker 装

容器化不是银弹。如果你的监控规模到了上千节点、需要大量分布式 proxy 和长期历史数据归档,或者面对严格合规审计、数据库必须跑在专用物理机上的场景,我还是建议走传统物理部署或虚机部署。另外,如果团队对 Docker 本身不熟,出了问题排不动,容器反而变成一个黑盒,这时候传统包里能直接看到配置文件、日志路径会更友好。我的原则很简单:容器编排当默认方案,规模或合规要求超出边界时再回到传统部署,两条路都走一遍就知道边界在哪里了。

2. 动手前的规划:镜像组合、数据目录和网络模型

我见过太多人把镜像拉下来 docker run 一把梭,等容器删掉重建时才发现数据没挂载、全没了。动手之前花十分钟把下面三件事定下来,后面能省一大截时间。

2.1 官方镜像怎么选:一张表说明白

Zabbix 官方在镜像仓库维护了一整套镜像,命名规律很好记:服务端镜像按数据库后端区分,Web 镜像按 Web 服务器和数据库后端区分。直接给结论:

组件推荐镜像说明
数据库postgres:16-alpine官方默认后端,资源占用更小
服务端zabbix/zabbix-server-pgsql:7.4-ubuntu-24.04对应 PostgreSQL 后端的变体
Webzabbix/zabbix-web-nginx-pgsql:7.4-ubuntu-24.04Nginx + PostgreSQL 组合
Agentzabbix/zabbix-agent:7.4-ubuntu-24.04自监控和被监控端通用

标签里的具体补丁号每天在变,动手前先 docker pull 拉一遍,以仓库实际列出的 tag 为准。我明确建议不要用第三方整合镜像,安全性和升级节奏都不可控,官方镜像出问题好歹还能去 GitHub 提 issue。

2.2 数据目录和磁盘空间预算

容器本身是无状态的,数据必须落在宿主机目录或命名卷上。我习惯用 bind mount 挂在项目目录下,结构长这样:

/opt/zabbix/ ├── docker-compose.yml ├── data/ │ ├── postgres/ │ ├── server/ │ │ ├── alertscripts/ │ │ ├── externalscripts/ │ │ └── snmptraps/ │ └── web/

磁盘预算给个经验值:100 台左右主机、默认保留策略(历史数据 90 天、趋势 365 天),PostgreSQL 数据目录每天大概涨 200~500 MB,具体取决于你建了多少个监控项。如果还要监控网络设备流量,关联的 item 会更多,空间按翻倍估。数据库目录一定要放在独立数据盘上,别和系统盘抢 I/O,等监控跑起来再搬家就麻烦多了。

2.3 端口清单与容器网络设计

Zabbix 需要关注四个端口:

端口归属作用
10051zabbix-serverAgent 主动上报数据的入口
10050zabbix-agent接收服务端被动拉取数据
8080 / 8443zabbix-webWeb 界面 HTTP 与 HTTPS 入口
5432postgres数据库,仅容器间内部访问

网络这块我用自定义 bridge 网络。容器之间靠服务名互相解析,比如 zabbix-server 访问数据库时写 postgres 而不是写 IP。为什么不建议用 host 网络?一是多个容器同时占宿主端口容易冲突;二是服务名解析这层被绕过了,换台机器部署时 IP 一变就抓瞎。agent 通信有两个方向:主动模式下 agent 连 server 的 10051 上报数据,被动模式下 server 连 agent 的 10050 拉取数据。部署时要让两条链路都通,后面排错会专门讲。

3. 编排文件逐段拆解:每个变量都不是白写的

直接把完整的 Compose 文件贴出来,然后逐段讲清楚为什么这样写。这是我在测试环境验证过、又调整过一轮的版本,可以直接抄。

services: postgres: image: postgres:16-alpine container_name: zabbix-postgres restart: unless-stopped environment: POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd_2024 POSTGRES_DB: zabbix volumes: - ./data/postgres:/var/lib/postgresql/data networks: - zbxnet zabbix-server: image: zabbix/zabbix-server-pgsql:7.4-ubuntu-24.04 container_name: zabbix-server restart: unless-stopped environment: DB_SERVER_HOST: postgres DB_SERVER_PORT: 5432 POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd_2024 POSTGRES_DB: zabbix ZBX_CACHESIZE: 256M ZBX_STARTPOLLERS: 8 ZBX_STARTPOLLERSUNREACHABLE: 4 ZBX_STARTPINGERS: 2 ZBX_STARTTRAPPERS: 4 ports: - "10051:10051" volumes: - ./data/server/alertscripts:/usr/lib/zabbix/alertscripts - ./data/server/externalscripts:/usr/lib/zabbix/externalscripts - ./data/server/modules:/var/lib/zabbix/modules - ./data/server/snmptraps:/var/lib/zabbix/snmptraps depends_on: - postgres networks: - zbxnet zabbix-web: image: zabbix/zabbix-web-nginx-pgsql:7.4-ubuntu-24.04 container_name: zabbix-web restart: unless-stopped environment: ZBX_SERVER_HOST: zabbix-server DB_SERVER_HOST: postgres DB_SERVER_PORT: 5432 POSTGRES_USER: zabbix POSTGRES_PASSWORD: zabbix_pwd_2024 POSTGRES_DB: zabbix PHP_TZ: Asia/Shanghai ports: - "8080:8080" - "8443:8443" depends_on: - zabbix-server networks: - zbxnet zabbix-agent: image: zabbix/zabbix-agent:7.4-ubuntu-24.04 container_name: zabbix-agent restart: unless-stopped environment: ZBX_SERVER_HOST: zabbix-server ZBX_HOSTNAME: "docker-host" ports: - "10050:10050" depends_on: - zabbix-server networks: - zbxnet networks: zbxnet: driver: bridge

3.1 数据库容器:账号、密码和存储

postgres 镜像的三个环境变量决定初始化时的账号、密码和库名。这里有一个很多人踩过的坑:这些变量只在数据目录为空时生效。如果 ./data/postgres 底下已经存在一份旧数据,你再改密码也没用,数据库仍是旧账号密码。我遇到过好几次这种情况,排查半天才发现是目录里残留旧库。所以首次部署时确认数据目录是空的,生产环境密码不要写死在 Compose 里,用 .env 文件引用或者交给配置管理系统。

数据库端口我故意没映射到宿主机,只让它待在容器网络内部,外部访问只能通过 Web 界面,少一个暴露面。如果你确实需要直连数据库排查问题,临时用 docker exec 进容器执行 psql 就够了。

3.2 Server 容器:自动建表背后的变量逻辑

zabbix-server 第一次启动时会自动完成数据库 schema 的创建和迁移,这就是它也要带一份 POSTGRES_* 环境变量的原因——它要用数据库账号连进去执行 DDL。DB_SERVER_HOST 填的是 postgres,依赖的就是同一个 zbxnet 网络里的服务名解析。

后面几个 ZBX_ 开头的变量是性能调参。ZBX_STARTPOLLERS 控制被动轮询进程数,主机多了之后优先加这个;ZBX_STARTPOLLERSUNREACHABLE 是专门处理不可达主机的进程数;ZBX_STARTPINGERS 是 ICMP ping 进程数;ZBX_CACHESIZE 是配置缓存大小。小规模部署按我文件里的值够用,等主机量上来再逐步调。注意这些参数改了要重启容器才生效。

server 挂载的 alertscripts 和 externalscripts 目录分别放告警脚本和外部检查脚本,snmptraps 目录用来接收被动 SNMP trap。现在不挂也能跑,但等你要用自定义脚本时,会发现没挂载就只能进容器里改,下次升级全丢。所以一开始就挂上,养成好习惯。

3.3 Web 容器:为什么它也要连数据库

很多人会疑惑:Web 前端直接走服务端 API 不就行了,为什么还要连数据库?因为最新数据页、仪表盘报表、趋势图这类功能是 Web 进程直连数据库读的,绕不开。所以 Web 容器同样要配 DB_SERVER_HOST 和 POSTGRES_* 变量,缺一个都会导致界面报错。

PHP_TZ 这个变量尤其关键,它决定 Web 端图表显示用的时区。如果不设置,容器默认按 UTC 时间跑,图表时间会比本地差 8 小时(取决于你所在时区),排查起来非常迷惑。我这里写了 Asia/Shanghai 作为示例,实际部署时按你业务所在的时区替换。

3.4 Agent 容器:自监控这条链路别省

一个常见误区是:只装 server 和 web 就收工了。没有 agent,你就没法从 UI 里看到 Zabbix 自身运行状态。把 zabbix-agent 容器一起拉起来,等会在第 4 节添加主机时,就能用它完成第一次完整的数据链路验证。ZBX_SERVER_HOST 告诉 agent 主动上报给哪个服务端,ZBX_HOSTNAME 是它自己的标识。agent 容器端口映射到宿主机 10050,是为了方便以后直接监控宿主机本身——把宿主机当一台设备加进去时,server 可以通过这台宿主机的 IP + 10050 来采集。

4. 从 docker compose up 到看见第一条监控数据

4.1 启动和日志观察的正确姿势

在 /opt/zabbix 目录下执行:

docker compose up -d docker compose ps

第一次启动别急着关终端,重点看两个容器的日志。先看 server:

docker compose logs -f zabbix-server

正常情况下你会看到数据库 schema 迁移的日志,一堆 CREATE TABLE、CREATE INDEX 往下刷,这个过程持续几分钟。等日志稳定下来,出现类似服务端启动完成、开始监听 10051 的字样,再进行下一步。再看一眼 web 日志有没有报数据库连接错误。很多人上来就开网页,页面半天打不开,其实就是迁移还没跑完,或者 web 连库失败了。

4.2 Web 向导和首登设置

打开浏览器访问 http://你的服务器IP:8080,会看到 7.4 的安装向导。因为数据库连接信息已经在环境变量里配置好了,向导里大部分检查项会直接通过。两个值得注意的点:如果提示时区不对,回去确认 PHP_TZ 是否设置正确;如果提示数据库连接失败,按第 5 节的排查链路处理。

默认管理员账号是 Admin,密码是 zabbix,登录后第一件事就是改密码。这个账号是全系统最高权限,留着默认密码,等于把监控大门的钥匙挂在门把手上。界面语言可以在用户设置里切换,7.4 的简体中文包覆盖得比较全,日常操作没问题;个别术语你觉得英文更准确,切回英文也方便。

4.3 添加第一台主机并验证数据链路

我习惯先监控 Zabbix 自身。进入 Monitoring → Hosts → Create host,填主机名 "Zabbix server",添加 Agent 接口。IP 地址填哪个?两个选择:如果被监控目标就是 agent 容器本身,可以填 agent 容器在 zbxnet 网络里的 IP,server 能直接访问;如果 agent 容器把 10050 端口映射到了宿主机,也可以填宿主机 IP。我演示用的是容器 IP 方式,更干净,不依赖宿主端口。

模板选 "Linux by Zabbix agent",顺便把 "Zabbix server health" 模板也加上,后者专门监控服务端自身性能。保存之后等几十秒,主机名旁边会出现绿色的 ZBX 标识,表示被动检查通了。如果想立刻确认链路,进 server 容器手动探测一把:

docker exec -it zabbix-server zabbix_get -s <agent容器IP> -p 10050 -k agent.ping

返回 1 就说明整条链路没问题。然后到 Latest data 页面搜 system.uptime 或者 agent.ping,看到具体的值在变化,监控系统就算真正跑起来了。

5. 安装期最容易翻车的五个问题,附完整排查链路

5.1 Web 界面报数据库连接失败

先别怀疑镜像有问题,按顺序查三样:环境变量、网络、数据库状态。

docker compose ps docker logs zabbix-web | tail -50 docker exec -it zabbix-postgres pg_isready -U zabbix -d zabbix

最常见原因是 Web 容器漏配 POSTGRES_PASSWORD,或者密码与 postgres 容器初始化时不一致。另一个隐蔽原因是 postgres 的数据目录里已经有一份旧数据——前面强调过,环境变量只在空目录时生效。有一次我排查一个案例,配置看起来全对但就是连不上,最后才发现挂载目录是从旧测试环境原样复制过来的,里面有旧库,账号密码跟新配置完全对不上。

5.2 Server 容器反复重启或初始化卡住

典型症状:docker compose ps 里 server 显示 Restarting,日志反复报数据库连接失败或者权限错误。排查链路是:先看数据库日志,再看数据目录属主,最后看磁盘空间。

docker logs zabbix-postgres | tail -50 ls -ld /opt/zabbix/data/postgres df -h

如果 postgres 数据目录属主不对或者权限是 root 持有,容器写不进去就会一直起不来。解决办法是调整目录属主到数据库容器对应 UID,或者停掉容器清空数据目录重新初始化。清空数据目录不可逆,动手前确认里面没有需要保留的监控数据。

5.3 主机上线显示红 ZBX 不可达

主机图标红了,先确认三点:接口地址是不是 server 网络可达的、10050 端口映射有没有生效、宿主机防火墙放没放行。在 server 容器里直接测最直观:

docker exec zabbix-server zabbix_get -s 10.0.0.10 -p 10050 -k agent.ping

宿主机防火墙要放行 10050(被动模式)和 10051(主动模式),如果服务器还有云平台安全组,也要同步加规则,这一步最容易漏。还有一种坑:给主机填的接口 IP 写成了 agent 容器 IP,但 agent 没加入 zbxnet 网络,server 根本找不到它。把 agent 加进同一个自定义网络,这类问题就解决了。

5.4 界面时间偏移和加载慢

时间偏移基本就是 PHP_TZ 的问题,改掉环境变量后重建 web 容器即可。加载慢要分情况:如果是首次打开某个大报表慢,多半是数据库在做数据聚合,属正常现象;如果是图表一直转圈,去看 server 日志有没有连接超时,再考虑调大 ZBX_CACHESIZE 或者检查磁盘 I/O。监控系统跑一段时间后,PostgreSQL 的 autovacuum 和统计信息更新也会让页面偶尔变慢,不用过度紧张。

5.5 容器删了数据会不会一起没了

这是个高频疑虑。只要 volumes 挂载正确,容器删掉重建数据都在。但如果你用的是匿名卷或者根本没挂载,执行 docker compose down -v 时数据库卷会被一并清理,那就真是数据全没了。所以挂载清单值得逐项核对:postgres 的 data、server 的 alertscripts/externalscripts/modules/snmptraps、web 的 modules/themes。宁可多挂,不要漏挂。

6. 长期运行的功课:备份、资源限制和升级路径

6.1 数据库备份的两种靠谱姿势

Zabbix 的核心数据全在 PostgreSQL 里,备份等于备份数据库。我推荐两种组合使用。

第一种是逻辑备份。直接进 postgres 容器用 pg_dump:

docker exec zabbix-postgres pg_dump -U zabbix -d zabbix -F c -f /tmp/zabbix.dump docker cp zabbix-postgres:/tmp/zabbix.dump ./zabbix-$(date +%F).dump

配合 crontab 每天凌晨执行一次,保留最近 7 份,中小规模环境完全够用。

第二种是卷快照。如果数据库目录所在数据盘支持快照,恢复速度比逻辑导入快得多。要点是快照前先把 server 容器停掉,确保库内没有正在进行的写入,避免快照出中间态。我见过有人图省事在线快照,恢复后遇到索引不一致,折腾两天。物理快照加上定期逻辑备份,是生产环境最稳妥的组合。

恢复时反向操作:把 dump 文件放回容器,用 pg_restore 还原。日常建议多做两次恢复演练,别等真的出故障才第一次试恢复流程。

6.2 给监控容器上资源锁和日志轮转

监控系统本身也是资源消费者,跑一段时间后,PostgreSQL 和 PHP 进程的内存占用都会缓慢爬升。我建议在 Compose 文件里给关键服务加上资源限制:

mem_limit: 1g cpus: "1.0"

单机使用 docker compose 时,mem_limit 和 cpus 就能生效。日志轮转也要提前设好,默认 json-file 模式不限制的话,日志文件能涨到几个 G:

logging: driver: json-file options: max-size: "50m" max-file: "3"

这套配置加进去之后再重新创建容器,资源占用和日志增长就都在可控范围内了。

6.3 从 7.4 往后的升级和回滚思路

官方每个补丁版本发布后,升级流程都是固定的四步:备份数据、docker compose pull、docker compose up -d、观察日志。服务端镜像启动时自动做 schema 迁移,Web 端跟着切到新版本,整个过程比传统升级省心太多。

回滚思路也简单:升级前记下当前镜像的完整 tag,出问题就 docker compose down,把镜像 tag 改回旧版本再 up -d。只要数据目录没动过,一般都能直接退回去。这里提醒一句,很多工具不支持跨大版本直接回退,比如数据库 schema 已经升上去了,旧版本服务端可能起不来。所以升级前做完整备份,永远是最重要的一步。

到这里,Docker 上安装 Zabbix 7.4 的完整链路就梳理完了。最后分享两句我自己的体会:第一,把 Compose 文件当成部署文档来维护,注释写清楚每段是干什么的,半年后回来看还能一次还原环境;第二,默认账号密码务必立刻改掉。监控系统记录着全网的资产和告警信息,它常常也是最容易被忽略的那个入口。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询