ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Docker容器化部署Zabbix监控系统:架构、实操与排障实战

2026/10/8 14:59:16 拓冰建站 浏览量
Docker容器化部署Zabbix监控系统:架构、实操与排障实战 自己折腾 Zabbix 一年多从裸机装到容器化部署中间踩过的坑能写满一本流水账。这篇就聊聊我目前最常用的部署方式——用 Docker 搭 Zabbix把整个架构、为什么这么选、具体怎么落地、常见问题怎么排查一次说清楚。Docker 搭建 Zabbix 最直观的价值是把原本要折腾半天的依赖环境、数据库初始化、定时任务配置全部打包成镜像一条命令拉起一套监控系统。它适合三类人一是测试环境想快速体验 Zabbix 的二是生产环境想摆脱 OS 版本绑定、方便整体迁移的三是被 CentOS 7.9 上那一堆 Python、OpenIPMI、libevent 依赖搞到崩溃的运维。不过在动手之前我先说点真话Docker 化 Zabbix 不只是docker run zabbix-server那么简单它牵扯到数据库持久化、网络模式、主动/被动监控链路、Web 与 Server 分离部署等一系列决策。1. 整体架构与设计思路1.1 为什么选择 Docker 而不是直接装 RPM 包传统裸机安装 Zabbix 是一个典型的环境地狱场景。Zabbix Server 依赖 PHP、Apache/Nginx、MySQL/PostgreSQL、Net-SNMP、libcurl、OpenIPMI 等一堆底层库5.0 和 6.0 对 PHP 版本要求还不一样7.0 直接要求 PHP 8.0。换一台最小化安装的 CentOS 7.9光补齐这些依赖就够喝一壶的更别提 PHP 版本还得从第三方源编译升级。Docker 方案把这些问题全部封装进镜像。Zabbix 官方提供了完整的容器化矩阵zabbix/zabbix-server-mysql、zabbix/zabbix-web-nginx-mysql、zabbix/zabbix-agent数据库也有配套的初始化逻辑。官方镜像的构建脚本直接继承了发行版的编译参数自带 OpenIPMI、SNMP 支持省掉了我们手动编译扩展的麻烦。生产环境用 Docker 还有一个隐性的好处——升级路径清晰。从 6.0 升 7.0 时裸机方案要考虑 PHP 版本迁移、配置文件差异、前端资源兼容性而容器方案只需要拉新镜像、迁移数据库Server 和 Web 的同步版本由镜像 tag 保证出问题的概率低得多。1.2 Zabbix 核心组件拆解Server、Web、Agent 各司其职一个完整的 Zabbix 架构包含四类角色组件职责端口容器化要点Zabbix Server数据采集调度、告警评估、触发器计算10051Trapper、10050Polling 时作为客户端核心进程需要连接数据库Zabbix Web前端界面PHP-FPM Nginx8080/80与 Server 解耦通过 PHP 连接 DBZabbix Agent部署在被监控主机上的采集器10050被动模式监听可以用容器但更推荐宿主机二进制方式数据库MySQL / PostgreSQL3306 / 5432强烈建议数据卷持久化很多人把 Zabbix Server 和 Web 容器当成一个整体实际上官方是拆开的。拆开的好处很明确Web 层做反向代理时不用影响 Server 进程API 压测时也不会占用采集进程的资源。热搜里有个词是web与zabbix分离指的就是把前端容器单独拎出来甚至部署到另一台机器上。这在容器化环境里几乎零成本只需要让 Server 和 Web 容器连同一个网络、访问同一个数据库即可。1.3 版本选型锁定 tag别用 latestZabbix 镜像的 tag 格式通常是version-database-os比如zabbix-server-mysql:7.0-centos-latest。我实际用下来建议锁两个维度大版本锁死比如 6.0 LTS 还是 7.0 LTS。Zabbix 官方对 LTS 版本提供更长的支持周期生产环境别追新6.0 和 7.0 的模板结构、API 路径有差异。操作系统底包官方镜像有alpine、ubuntu、centos几种底包。Alpine 版本体积小约 200MB但遇到需要编译额外 Agent 插件的情况会比较难受CentOS 底包兼容性最好跟裸机环境行为最接近。另外强调一点不要在 compose 文件里写latest。Zabbix 的大版本升级通常伴随着数据库 Schema 变更latest漂移会导致 Web 升级了、Server 没升级前端报数据库版本不兼容。用固定 tag 才能真正享受镜像的可复现性。2. 核心细节解析网络、存储、时区与监控模式2.1 Agent 主动与被动模式在容器环境下的差异Zabbix Agent 的工作模式有两种。被动模式是 Server 主动连接 Agent 的 10050 端口去取数据这种模式要求 Server 到 Agent 的网络可达且在容器化部署时Agent 容器需要把 10050 端口暴露出来。主动模式则是 Agent 直接连接 Server 的 10051 端口上报数据Agent 需要配置ServerActive指向 Server 的地址。我在容器环境里的经验是被监控对象如果是宿主机自身比如用容器监控物理机 CPU、内存、磁盘强烈建议用 agent2 二进制部署在宿主机上而不是再套一层 Agent 容器。原因有二一是宿主机上的/proc、/sys文件系统挂载进容器会有隔离偏差磁盘利用率、网络速率计算会不准确二是被监控目标本身就是宿主机时Agent 容器跟宿主机处于不同网络命名空间Server 如果用被动模式反而多一层端口映射和 NAT 的故障点。如果是监控容器集群本身的资源比如监控 MySQL 容器实例那 Agent 容器跟业务容器放同一个自定义 bridge 网络里走 10051 主动上报更省事不用刻意映射 10050 端口。2.2 端口规划与网络模式选择Zabbix 涉及三个关键端口10051/tcpZabbix Server 的 Trapper 端口主动模式 Agent 上报数据的入口必须对 Agent 可达。10050/tcpAgent 监听端口被动模式下等待 Server 来拉数据仅在监听端口场景需要容器映射。8080/tcpWeb 界面端口通常映射到宿主机某个端口对外提供访问。Docker 网络模式我推荐创建自定义 bridge 网络docker network create zabbix-net并把所有 Zabbix 组件加到这个网络中。在这个网络里容器之间通过服务名直接通信比如 Server 连接数据库时用mysql这个主机名Web 连接数据库时也直接用mysql主机名这种内部 DNS 解析是 Docker 自带的不用再去硬编码 IP。如果非要用--network host模式我提醒一句host 模式在 Linux 下会让容器直接共享宿主机网络命名空间Zabbix Server 的 10051 端口和被监控宿主机上其他服务的端口可能冲突而且 Web 容器的 Nginx 配置里绑定的是镜像内的端口host 模式下不容易灵活调整监听端口。除非你对网络很熟否则别这么干。2.3 数据持久化数据库状态必须外置Zabbix 的业务状态全在数据库里——主机列表、模板、触发器、历史数据、告警事件。容器销毁后如果数据库数据卷不保留等于整个监控系统归零。我用 Docker 搭 Zabbix 时第一件事就是规划数据卷。MySQL 容器挂载本地目录时建议直接在 compose 里指定volumes映射命名卷或本地路径。实际工作中我更推荐本地路径比如/data/zabbix/mysql因为备份和维护时直接用tar就能打包不用绕一层docker run --volumes-from的复杂操作。Web 容器里也有一个隐蔽的持久化点/usr/share/zabbix/modules和/etc/zabbix/web。前端如果改过字体、安装过模块容器重启后会丢失建议也挂载出来。2.4 时区与中文乱码问题这是大家最容易踩的坑。Zabbix Server 容器默认时区是 UTCWeb 界面用 UTC 会导致告警时间比北京慢 8 小时前端界面显示中文时如果容器里没有中文字体图表上的中文文字全是方框乱码。解决方案分两步一是所有组件统一设置TZAsia/Shanghai环境变量Zabbix Server、Web、Agent 容器都要设二是给 Web 容器挂载中文字体。我一般从宿主机/usr/share/fonts/chinese/目录挂一个msyh.ttf进去同时修改 Web 容器里的 PHP 配置date.timezone。具体操作在后面实操章节详细说。3. 实操部署从零开始用 Docker Compose 拉起 Zabbix3.1 环境准备Docker 安装与镜像加速我的部署环境是一台 CentOS 7.9 服务器。CentOS 7.9 上安装 Docker 有点历史遗留问题需要处理默认源里的docker是老版本需要用官方源或阿里云源安装docker-ce。# 卸载旧版本如果有 yum remove -y docker docker-client docker-common docker-engine # 安装依赖 yum install -y yum-utils device-mapper-persistent-data lvm2 # 配置阿里云源 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装 Docker yum install -y docker-ce docker-ce-cli containerd.io # 启动 Docker systemctl start docker systemctl enable docker安装完成后立刻配镜像加速不然拉 Zabbix 这种大型镜像会非常痛苦。修改/etc/docker/daemon.json{ registry-mirrors: [ https://docker.m.daocloud.io, https://docker.mirrors.ustc.edu.cn ] }重启 Docker 使配置生效systemctl restart docker。这里实测下来不同加速源在不同网络环境下的速度差异很大建议多配几个Docker 会按顺序尝试。3.2 编写 docker-compose.yml参数逐个解释我用 Docker Compose 管理整套 ZabbixCompose 文件是部署的核心。以下是我在 6.0 LTS 版本上验证过的完整配置version: 3.8 networks: zabbix-net: driver: bridge volumes: mysql-data: services: mysql: image: mysql:8.0.36 container_name: zabbix-mysql networks: - zabbix-net ports: - 33061:3306 environment: MYSQL_ROOT_PASSWORD: ZabbixRoot123 MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: ZabbixUser123 TZ: Asia/Shanghai command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_bin - --default-authentication-plugincaching_sha2_password volumes: - mysql-data:/var/lib/mysql healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -pZabbixRoot123] interval: 10s timeout: 5s retries: 5 zabbix-server: image: zabbix/zabbix-server-mysql:6.0-centos-latest container_name: zabbix-server networks: - zabbix-net ports: - 10051:10051 environment: DB_SERVER_HOST: mysql DB_SERVER_PORT: 3306 MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: ZabbixUser123 TZ: Asia/Shanghai volumes: - ./zabbix-data/alertscripts:/usr/lib/zabbix/alertscripts - ./zabbix-data/externalscripts:/usr/lib/zabbix/externalscripts depends_on: mysql: condition: service_healthy zabbix-web: image: zabbix/zabbix-web-nginx-mysql:6.0-centos-latest container_name: zabbix-web networks: - zabbix-net ports: - 8080:8080 environment: DB_SERVER_HOST: mysql MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: ZabbixUser123 PHP_TZ: Asia/Shanghai TZ: Asia/Shanghai volumes: - ./zabbix-data/fonts:/usr/share/zabbix/assets/fonts:ro - ./zabbix-data/modules:/usr/share/zabbix/modules:ro depends_on: - zabbix-server这份配置里几个细节值得说明。DB_SERVER_HOST: mysql用的是 compose 服务名Docker 内嵌 DNS 会自动解析到 MySQL 容器的 IP。这里千万别写localhost因为容器之间是隔离的localhost指向容器自己。MySQL 的加密插件参数--default-authentication-plugincaching_sha2_password是兼容 Zabbix 6.0 的关键。Zabbix Server 是编译好的二进制用的是 C 库连接 MySQL对caching_sha2_password支持性有坑老版本 Zabbix 必须用mysql_native_password。如果像我一样用 MySQL 8.0并且 Zabbix 6.0 连接报认证失败在 MySQL 命令行里执行ALTER USER zabbix% IDENTIFIED WITH mysql_native_password BY ZabbixUser123;这是一个极其常见的坑直接决定你健康检查那关能不能过。PHP_TZ和TZ两个环境变量同时设是为了保证 Web 前端的时间显示和 Server 端的告警评估时间一致。3.3 启动与验证在 compose 文件所在目录执行docker compose up -d首次启动会拉镜像MySQL 初始化需要十几秒Zabbix Server 启动后会自动执行数据库 Schema 升级官方镜像内置了初始化 SQL 脚本。等待一分钟后查看容器状态docker compose ps正常情况下三个容器都是running。观察日志重点看 zabbix-server 容器是否报数据库连接错误docker logs zabbix-server --tail 50日志里出现Housekeeper process started和server #0 started表示 Zabbix Server 核心进程正常。浏览器访问http://服务器IP:8080看到 Zabbix 登录页面就成功了。默认账号密码是Admin / zabbix。3.4 Agent 客户端部署监控第一台 Linux 主机Agent 是整个监控链路上最容易被忽视、又最容易出问题的环节。这里我区分两种情况。情况一用容器跑 Agent 监控宿主机。docker run -d \ --name zabbix-agent \ --network host \ --restart unless-stopped \ -e ZBX_HOSTNAMECentOS-192.168.1.100 \ -e ZBX_SERVER_HOST192.168.1.10 \ -e ZBX_ACTIVE_ALLOWtrue \ zabbix/zabbix-agent2:6.0-centos-latest注意这里用的--network host目的是让 Agent 容器直接看到宿主机的物理网络接口这样 Server 用被动模式连宿主机 IP 的 10050 端口就能取到数据。如果不用 host 模式必须在启动时把 10050 映射到宿主机而且 Agent 里看到的/proc是容器的不是宿主机的采集的 CPU 利用率数据会严重失真。情况二宿主机直接装二进制 Agent生产环境我更推荐。RPM 包方式装 Agent 只需要两步rpm -Uvh https://repo.zabbix.com/zabbix/6.0/rhel/7/x86_64/zabbix-release-6.0-4.el7.noarch.rpm yum install -y zabbix-agent2然后修改/etc/zabbix/zabbix_agent2.conf三个参数Server192.168.1.10 # Zabbix Server 的 IP被动模式白名单 ServerActive192.168.1.10 # Server 的 IP主动模式上报地址 HostnameCentOS-Node1 # 这个需要和前端添加主机时填的主机名完全一致启动 Agentsystemctl start zabbix-agent2 systemctl enable zabbix-agent2在 Zabbix Web 界面添加主机时主机的IP 地址填宿主机 IP端口填 10050模板选Linux by Zabbix agent active或Linux by Zabbix agent。我个人的习惯是选 active 模板因为主动模式由 Agent 发起连接不用 Server 额外开入站规则防火墙好配很多。4. 常见问题与排查技巧实录4.1 镜像下载慢、超时怎么办Docker 在国内拉官方镜像经常卡死尤其是 Zabbix 这种多层镜像。除了前面说的配置镜像加速之外还有一个暴力但有效的办法换镜像源后重启 Docker再重新拉取如果某个源不行切换到另一个源。实测下来 Daocloud 源速度不错USTC 源偶尔会对部分镜像 404。另外可以合并拉取减少并发层数docker pull zabbix/zabbix-server-mysql:6.0-centos-latest如果网络实在太差可以考虑在 Docker Hub 页面找人工下架时机的镜像 tag或者从内网导出一份离线镜像包这个在公司内网环境尤其管用。4.2 Docker 服务启动失败failed to start docker application container enginesystemctl start docker直接报这个错常见原因有三个daemon.json语法错误、iptables 相关组件缺失、内核 IP 转发关闭。排查步骤# 查看详细日志 journalctl -u docker --no-pager | tail -50 # 手动启动 docker看前台输出 dockerd --debug如果日志里提到iptables无法访问多半是内核模块没加载modprobe iptable_nat modprobe iptable_filter echo 1 /proc/sys/net/ipv4/ip_forward如果日志提到overlay2错误检查内核版本是不是低于 4.0CentOS 7 默认内核 3.10部分老版本 Docker 支持不佳升级内核或改用vfs存储驱动可解。4.3 Agent 显示不可达网络链路逐段排查前端添加主机后主机状态一直灰色提示 Zabbix agent is not available。我总结了一个三段式排查法第一段测试 Server 到 Agent 的 10050 端口连通性# 在 Zabbix Server 容器里执行 docker exec -it zabbix-server bash yum install -y nmap-ncat nc -vz 192.168.1.101 10050如果连接失败检查 Agent 进程是否启动、防火墙是否放行 10050 端口。CentOS 7 上有个隐蔽坑装了 firewalld 后即使systemctl stop firewalld重启后又会自启动建议systemctl disable firewalld或在防火墙规则里放行。第二段确认 Agent 配置里的Server参数是否包含 Zabbix Server 的 IP。Agent 的Server是白名单机制如果填了 127.0.0.1Server 即使网络通Agent 也会直接忽略连接。第三段检查被动模式下 Server 用的主机名。前端主机配置里如果填了 DNS而 Agent 的Hostname参数不匹配也会出现频繁断连。我一般前端直接填 IP不开自动 DNS 解析少一层故障。4.4 告警一直显示问题状态如何手动消除很多新手困惑处理完故障后手动点击操作告警还是问题状态。记住关键点Zabbix 的告警是事件驱动的不是手动消除的。告警恢复的前提是触发器条件从 true 变回 false此时系统会自动生成一个恢复事件。你要做的不是手动改状态而是修复指标本身。如果指标恢复正常但告警依然存在可能的原因有这个指标走的是主动模式Agent 缓存了旧数据还没上报新值。触发器表达式用了nodata()或last()这类函数对时间窗口敏感等待几个周期看效果。触发器配置了多个条件且有and关系其中一个条件尚未恢复。实操排查建议打开监控 - 最新数据找到对应 item查看最近 30 分钟的数据是否还在更新最新值。如果一直没新数据问题就回到了 Agent 链路如果有新数据且已经恢复正常值一般下个评估周期默认 30 秒自动恢复。4.5 Web 与 Server 分离部署、Postman 调试 APIWeb 与 Zabbix 分离在容器架构下很好实现你可以把 compose 文件拆成两部分一部分在监控服务器上只跑 MySQL Zabbix Server另一部分在前面那台机器上跑 Web 容器Web 容器的DB_SERVER_HOST指向 MySQL 的宿主机 IPZBX_SERVER_HOST指向 Zabbix Server 的宿主机 IP前提是这两个 IP 在网络上互通。分离部署后调 API 是绕不开的话题。用 Postman 调试 Zabbix API 时完整流程是POST http://192.168.1.10:8080/api_jsonrpc.php Content-Type: application/json-rpc { jsonrpc: 2.0, method: user.login, params: { username: Admin, password: zabbix }, id: 1 }拿到 token 后再去调host.get、item.get、trigger.get。这里有个细节Zabbix API 的用户名密码认证方式在 6.0 之后开始弱化推荐用 API token 认证方便点在 Web 界面 用户-API tokens 里直接生成免去密码过期问题。调用时把auth字段换成 token 字符串即可。4.6 中文乱码与字体问题Web 界面选了中文语言后图形界面的中文全部是方块这是典型的字体缺失。Zabbix Web 容器用的默认字体是 DejaVu Sans不支持中文渲染。解决办法# 在宿主机准备字体 mkdir -p /data/zabbix/fonts # 从 Windows 或其它渠道拷贝一个中文字体比如 msyh.ttf cp msyh.ttf /data/zabbix/fonts/ # 修改 Web 容器里的字体配置 docker exec -it zabbix-web bash cd /usr/share/zabbix/assets/fonts # 备份原字体替换为新字体 mv graphfont.ttf graphfont.ttf.bak cp /data/zabbix/fonts/msyh.ttf /usr/share/zabbix/assets/fonts/graphfont.ttf注意替换后要清一下浏览器缓存不然看到的还是旧的字体文件。4.7 Docker 权限问题permission denied while trying to connect to the Docker daemon socket新装 Docker 后非 root 用户执行 docker 命令会报 permission denied。这个不是 Docker 本身问题而是用户没有加入docker用户组sudo usermod -aG docker $USER newgrp docker然后重新登录 shell。再说一个安全提醒把普通用户加进 docker 组等于给了这个用户 root 权限因为 docker 组用户可以通过挂载宿主机目录来提权。生产服务器上如果只有专职运维用问题不大如果有多个协作者建议用sudo来管理 docker 命令而不是拉组权限。5. 我的一些实操经验总结最后分享几个自己踩过坑之后形成的习惯。第一所有 Zabbix 组件的时间必须一模一样。Server、Web、Agent、MySQL四个容器一个TZ环境变量都不能漏。否则你会看到 Agent 采集的数据在时间轴上错位 8 小时告警评估出的时间跟实际故障时间对不上排查起来极其痛苦。第二数据库备份永远比配置备份重要。Zabbix 的前端、模板、脚本都可以重新配唯独历史数据和监控拓扑在数据库里。我每周自动全量备份一次 MySQL 数据卷另外用mysqldump做一次逻辑备份防止数据卷文件系统损坏这种极端情况。具体命令docker exec zabbix-mysql mysqldump -uzabbix -pZabbixUser123 zabbix | gzip zabbix_$(date %F).sql.gz第三Web 容器里的 Nginx 默认只监听 8080如果想用标准 80 端口直接把宿主机端口映射改成80:8080即可不用进容器改配置。第四安装 Zabbix 7.0 时镜像 tag 里的 centos 底包会变成almalinux这是上游发行版调整不是 Zabbix 官方的问题不用慌。Docker 部署 Zabbix 的整体思路概括起来就一句话把架构拆清楚、把持久化做好、把时间统一剩下的交给镜像去处理。这套方案从 5.0 用到 6.0再平滑升级到 7.0一直是稳定可靠的。如果照着这篇部署过程中遇到其他问题欢迎在评论里带上你的日志片段我看到了会帮你拆一拆。