ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker部署Zabbix监控系统:从环境搭建到API告警消除实战

Docker部署Zabbix监控系统:从环境搭建到API告警消除实战 简介这份资源面向需要在 Linux 服务器上快速搭建监控平台的运维人员与开发者提供用 Docker 部署 Zabbix 的完整代码包解决传统安装依赖繁琐、环境配置易出错的问题。压缩包共 5 个文件约 11KB以 docker-compose.yml 为核心编排文件配合 README.md 说明文档、index.html 页面、.gitignore 与 .inscode 配置覆盖容器定义、环境变量与端口映射等关键内容结构精简便于直接复用。资源同时给出两种部署思路一是通过 Compose 一键启动 Zabbix 服务、MySQL 数据库与前端二是借助宝塔面板已有数据库创建 Zabbix 容器读者可按现有环境灵活选择。目前已有 45 人学习适合希望快速落地 CPU、内存、磁盘与网络流量监控及报警能力的初、中级运维人员参考。1. 从一台干净的 CentOS 到能告警的 ZabbixDocker 安装到底省掉了什么如果你被 Zabbix 的 LAMP 依赖链折磨过——PHP 版本对不上、MySQL 字符集报错、SELinux 拦端口、前端白屏——那你大概率会认同一个结论用 Docker 装 Zabbix省掉的不是几条命令而是整套「环境玄学」。这份资源就是围绕 Docker 部署 Zabbix 的完整代码包核心价值在于把 Zabbix Server、Web 前端、MySQL 数据库、Java Gateway 四个组件的版本、网络、数据卷全部用编排文件固化下来你拿到手改几个参数就能跑起来。它适合两类人一是第一次搭监控、不想在依赖上翻车的运维新手二是需要快速起一套测试环境、验证模板和告警链路的老手。下面我按「先跑通、再拆解、最后避坑」的顺序把这份代码包拆开讲透。2. 环境准备与镜像选型为什么是 MySQL 8 而不是官方默认的 MariaDB2.1 宿主机前置条件与 Docker 安装Zabbix 官方镜像对宿主机的要求其实不高但有几个硬门槛必须先过。CPU 至少 2 核、内存 4GB 起步Zabbix Server 加 MySQL 加前端2GB 会 OOM磁盘留 20GB 给数据卷。操作系统我一般用 CentOS 7.9 或 Ubuntu 22.04两者在 Docker 安装上略有差异。CentOS 7.9 的 Docker 安装走 yum 源注意 CentOS 7 已停止维护需要先把 yum 源指向 vault# CentOS 7.9 安装 Docker CE sudo yum install -y yum-utils # 官方源已失效改用 vault 归档源 sudo sed -i s/mirrorlist/#mirrorlist/g /etc/yum.repos.d/CentOS-* sudo sed -i s|#baseurlhttp://mirror.centos.org|baseurlhttp://vault.centos.org|g /etc/yum.repos.d/CentOS-* sudo yum install -y docker-ce docker-ce-cli containerd.io sudo systemctl enable --now docker # 验证 docker versionUbuntu 22.04 则用 apt步骤更顺# Ubuntu 22.04 安装 Docker sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin sudo systemctl enable --now docker参数说明docker-compose-plugin提供docker compose子命令比老的docker-compose二进制更省心。安装完记得把当前用户加进 docker 组否则每条命令都要 sudosudo usermod -aG docker $USER然后重新登录生效。提示如果你在 Windows 上用 Docker Desktop需要先在 BIOS 里开启虚拟化否则会报virtualization support not detected。这个报错和 Zabbix 无关是 Docker Desktop 自身的启动门槛。2.2 镜像选型MySQL 8 与 Zabbix 6.0 LTS 的搭配逻辑这份代码包用的是 Zabbix 6.0 LTS 系列镜像数据库选了 MySQL 8.0 而不是官方 compose 示例里常见的 MariaDB。原因有三个第一MySQL 8 的默认字符集是 utf8mb4Zabbix 前端中文和特殊符号不会乱码省掉改字符集的步骤第二MySQL 8 的认证插件默认 caching_sha2_passwordZabbix 6.0 的镜像已经内置了对应驱动不存在连不上的问题第三很多生产环境本来就在用 MySQL 8测试环境和生产环境保持一致迁移时少一层变量。镜像清单如下全部来自 Docker Hub 官方或 Zabbix 官方仓库组件镜像用途数据库mysql:8.0存储 Zabbix 配置与历史数据Zabbix Serverzabbix/zabbix-server-mysql:6.0-centos核心采集与告警引擎Web 前端zabbix/zabbix-web-nginx-mysql:6.0-centosNginx PHP 提供 Web UIJava Gatewayzabbix/zabbix-java-gateway:6.0-centos监控 JMX 应用可选选6.0-centos标签而不是latest是因为 LTS 版本的支持周期到 2027 年且标签固定不会因为上游更新导致某天拉到的镜像行为突变。这是我在生产环境踩过的坑用latest标签某次重建容器后前端直接起不来排查半天发现是镜像底层 PHP 版本变了。2.3 目录结构与数据卷规划在跑 compose 之前先把宿主机目录建好。数据卷规划的核心原则是数据库数据、Zabbix 配置、告警脚本三样必须持久化容器删了数据不能丢。# 创建项目目录结构 mkdir -p /opt/zabbix/{mysql-data,zabbix-lib,alertscripts,externalscripts} cd /opt/zabbix # 设置 MySQL 数据目录权限MySQL 容器内 uid 是 999 chown -R 999:999 /opt/zabbix/mysql-data # 告警脚本目录给执行权限 chmod 755 /opt/zabbix/alertscripts参数说明mysql-data挂载到容器内/var/lib/mysql这是 MySQL 的数据目录权限必须是 999:999否则容器启动时报Permission denied。zabbix-lib挂载到/var/lib/zabbix存放 Zabbix 的缓存和外部脚本。alertscripts挂载到/usr/lib/zabbix/alertscripts你写的告警脚本放这里Zabbix 才能调用。externalscripts挂载到/usr/lib/zabbix/externalscripts用于自定义监控项的外部脚本。注意不要用 Docker 命名卷named volume代替 bind mount。命名卷在排查问题时很难直接看到文件bind mount 出问题时你ls一下目录就知道数据在不在。这是血泪经验别问我是怎么知道的。3. 编排文件逐段拆解docker-compose.yml 里每个参数都在干什么3.1 完整的 docker-compose.yml 与网络设计这份代码包的核心是一个docker-compose.yml四个服务通过自定义 bridge 网络通信。先看完整文件再逐段拆。version: 3.8 services: mysql-server: image: mysql:8.0 container_name: zabbix-mysql restart: unless-stopped environment: MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd_2024 MYSQL_ROOT_PASSWORD: root_pwd_2024 TZ: Asia/Shanghai command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_bin - --default-authentication-pluginmysql_native_password volumes: - ./mysql-data:/var/lib/mysql networks: - zabbix-net zabbix-server: image: zabbix/zabbix-server-mysql:6.0-centos container_name: zabbix-server restart: unless-stopped environment: DB_SERVER_HOST: mysql-server MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd_2024 TZ: Asia/Shanghai volumes: - ./zabbix-lib:/var/lib/zabbix - ./alertscripts:/usr/lib/zabbix/alertscripts - ./externalscripts:/usr/lib/zabbix/externalscripts ports: - 10051:10051 depends_on: - mysql-server networks: - zabbix-net zabbix-web: image: zabbix/zabbix-web-nginx-mysql:6.0-centos container_name: zabbix-web restart: unless-stopped environment: ZBX_SERVER_HOST: zabbix-server DB_SERVER_HOST: mysql-server MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd_2024 PHP_TZ: Asia/Shanghai ZBX_SERVER_NAME: Zabbix Monitoring ports: - 8080:8080 depends_on: - mysql-server - zabbix-server networks: - zabbix-net zabbix-java-gateway: image: zabbix/zabbix-java-gateway:6.0-centos container_name: zabbix-java-gateway restart: unless-stopped networks: - zabbix-net networks: zabbix-net: driver: bridge逻辑说明四个服务全部接入zabbix-net这个自定义 bridge 网络容器之间用服务名互相访问比如zabbix-server里配DB_SERVER_HOST: mysql-serverDocker 内置 DNS 会解析到 MySQL 容器的 IP。这样你不需要记任何 IP重建容器后 IP 变了也不影响。depends_on只保证启动顺序不保证 MySQL 已经初始化完成所以第一次启动时 Zabbix Server 可能会重试几次才连上数据库这是正常的。3.2 关键环境变量与端口映射的参数含义环境变量是这套编排的灵魂改错一个就连不上。逐个说清楚MYSQL_DATABASE: zabbix告诉 MySQL 容器初始化时创建名为 zabbix 的库Zabbix Server 和 Web 都用这个库名。MYSQL_USER和MYSQL_PASSWORD是应用连接用的账号不是 root。MYSQL_ROOT_PASSWORD是 root 密码只在初始化时用一次之后可以不管。command里的三个参数很关键。--character-set-serverutf8mb4和--collation-serverutf8mb4_bin保证数据库层字符集正确utf8mb4_bin是 Zabbix 官方推荐的排序规则用utf8mb4_general_ci在某些查询下会有性能差异。--default-authentication-pluginmysql_native_password是为了兼容性虽然 Zabbix 6.0 支持 caching_sha2_password但如果你后面要接一些老版本的客户端工具native_password 更省事。端口映射方面Zabbix Server 的10051是主动模式和被动模式采集的端口必须暴露给被监控主机。Web 前端的8080是宿主机端口映射到容器内的 8080Nginx 监听端口你访问http://宿主机IP:8080就能打开 Web UI。MySQL 的 3306 我没有映射到宿主机因为没必要——Zabbix 组件都在同一个网络里外部不需要直连数据库。如果你确实要用客户端连进去排查临时加一行- 3306:3306即可排查完删掉。TZ和PHP_TZ都设成Asia/Shanghai这是为了让告警时间、图表时间轴和你的本地时间一致。不设的话默认 UTC你会看到告警时间差 8 小时排查问题时容易误判。3.3 启动流程与首次访问验证编排文件写好后启动顺序和验证步骤要按部就班。# 进入项目目录 cd /opt/zabbix # 后台启动所有服务 docker compose up -d # 查看启动状态等待所有容器变成 healthy 或 running docker compose ps # 实时看 Zabbix Server 日志确认数据库连接成功 docker compose logs -f zabbix-server日志里看到database is up and running和server #0 started就说明 Server 起来了。如果一直刷cannot connect to database别慌等 30 秒MySQL 首次初始化需要时间。超过 2 分钟还连不上再去查 MySQL 容器日志。Web 前端验证浏览器打开http://宿主机IP:8080默认账号Admin默认密码zabbix。登录后第一件事是改密码第二件事是检查Administration → General → GUI里的时区设置确认是Asia/Shanghai。提示如果页面显示Zabbix server is not running先别改配置。等一分钟刷新大概率是 Server 还在初始化数据库表结构。首次启动要建一百多张表慢是正常的。4. 避坑与排查Docker 装 Zabbix 最容易翻车的五个地方4.1 现象Web 页面报「Database error」或白屏原因MySQL 8 的认证插件或字符集不匹配。Zabbix Web 容器里的 PHP 驱动如果连不上 MySQL前端直接白屏日志里会有Access denied或Unknown character set。解决先确认docker compose logs mysql-server里没有报错再进 MySQL 容器手动验证# 进 MySQL 容器 docker exec -it zabbix-mysql mysql -uzabbix -pzabbix_pwd_2024 -e SHOW DATABASES; # 如果报认证错误检查 compose 里的 default-authentication-plugin 参数是否生效 docker exec -it zabbix-mysql mysql -uroot -proot_pwd_2024 -e SELECT user,host,plugin FROM mysql.user;如果plugin列显示caching_sha2_password而不是mysql_native_password说明command参数没生效。检查 compose 文件里command的缩进YAML 对缩进极其敏感少一个空格就解析失败。4.2 现象Zabbix Server 容器反复重启原因数据卷权限不对或者 MySQL 还没初始化完 Server 就急着连。前者报Permission denied后者报Connection refused。解决先看日志定位是哪种。权限问题就重新chown -R 999:999 /opt/zabbix/mysql-data。连接问题就加restart: unless-stopped编排里已经有了让 Server 自动重试。如果反复重启超过 5 次把depends_on改成带健康检查的写法depends_on: mysql-server: condition: service_healthy然后在 MySQL 服务下加健康检查healthcheck: test: [CMD, mysqladmin, ping, -h, localhost, -uroot, -proot_pwd_2024] interval: 10s timeout: 5s retries: 5这样 Server 会等 MySQL 真正就绪后再启动避免无谓的重启循环。4.3 现象被监控主机连不上 Zabbix Server 的 10051 端口原因防火墙没放行或者 Zabbix Server 的10051只监听了容器内网。编排里已经做了10051:10051映射但宿主机防火墙可能拦了。解决CentOS 7 用firewall-cmd --add-port10051/tcp --permanent firewall-cmd --reloadUbuntu 用ufw allow 10051/tcp。然后在被监控主机上用telnet 宿主机IP 10051测试通了再配 Zabbix Agent。如果 telnet 不通但容器日志正常检查docker compose ps里端口映射那一列是不是0.0.0.0:10051-10051/tcp。4.4 现象告警脚本不执行或者执行了但发不出消息原因脚本没放对目录或者没有执行权限或者脚本里的路径在容器内不存在。解决告警脚本必须放在/opt/zabbix/alertscripts下这个目录挂载到容器内的/usr/lib/zabbix/alertscripts。脚本要有执行权限chmod x首行 shebang 要写对。在 Zabbix Web 里配置告警媒介时脚本名写文件名不要写路径。测试时用docker exec -it zabbix-server /usr/lib/zabbix/alertscripts/你的脚本.sh 参数手动跑一遍看报什么错。4.5 现象中文乱码或图表时间不对原因数据库字符集不是 utf8mb4或者 PHP 时区没设。解决数据库字符集在 compose 的command里已经指定如果还是乱码进 MySQL 查SHOW VARIABLES LIKE character%;确认character_set_server是utf8mb4。时区问题检查 Web 容器的PHP_TZ和 Server 容器的TZ两个都要设。改完环境变量后docker compose down docker compose up -d重建容器光 restart 不会重新读取环境变量。5. 进阶用 Zabbix API 批量拉取监控数据与告警手动消除5.1 用 API 获取主机 CPU、内存、磁盘数据Web UI 看图表方便但要做报表或对接其他系统API 更直接。Zabbix 6.0 的 API 走http://宿主机IP:8080/api_jsonrpc.php先拿 token再查数据。import requests import json # 配置 ZABBIX_URL http://192.168.1.100:8080/api_jsonrpc.php USER Admin PASSWORD zabbix # 第一步登录获取 token def get_token(): payload { jsonrpc: 2.0, method: user.login, params: {username: USER, password: PASSWORD}, id: 1 } resp requests.post(ZABBIX_URL, jsonpayload) return resp.json()[result] # 第二步查主机列表 def get_hosts(token): payload { jsonrpc: 2.0, method: host.get, params: { output: [hostid, host, name], selectInterfaces: [ip] }, auth: token, id: 2 } resp requests.post(ZABBIX_URL, jsonpayload) return resp.json()[result] # 第三步查指定主机的 CPU 使用率监控项 def get_cpu_items(token, hostid): payload { jsonrpc: 2.0, method: item.get, params: { output: [itemid, name, lastvalue, units], hostids: hostid, search: {name: CPU utilization}, sortfield: name }, auth: token, id: 3 } resp requests.post(ZABBIX_URL, jsonpayload) return resp.json()[result] if __name__ __main__: token get_token() hosts get_hosts(token) for h in hosts: print(f主机: {h[name]} ({h[host]})) items get_cpu_items(token, h[hostid]) for item in items: print(f {item[name]}: {item[lastvalue]} {item[units]})逻辑说明user.login返回的 token 在后续请求里放在auth字段。host.get拿主机列表和接口 IP。item.get用search模糊匹配监控项名称lastvalue是最近一次采集的值。参数说明output控制返回哪些字段字段越少响应越快search是模糊匹配精确匹配用filter。这套代码可以直接改成拉内存和磁盘把search的关键词换成Memory utilization和Space utilization即可。5.2 告警手动消除与 API 确认Zabbix 的告警不会自动消失需要手动确认acknowledge或等触发器恢复。批量确认用event.acknowledge方法def acknowledge_event(token, eventid, message已处理): payload { jsonrpc: 2.0, method: event.acknowledge, params: { eventids: eventid, action: 6, # 1关闭, 2确认, 4加消息, 6确认加消息 message: message }, auth: token, id: 4 } resp requests.post(ZABBIX_URL, jsonpayload) return resp.json() # 先查未确认的告警 def get_unack_events(token): payload { jsonrpc: 2.0, method: event.get, params: { output: [eventid, name, severity, clock], select_acknowledges: [message], acknowledged: False, severity: 4, # 4High, 5Disaster sortfield: [clock], sortorder: DESC, limit: 20 }, auth: token, id: 5 } resp requests.post(ZABBIX_URL, jsonpayload) return resp.json()[result]参数说明action是位掩码6等于2|4表示确认并加消息。severity过滤告警级别4 是 High5 是 Disaster按需调整。acknowledged: False只查未确认的。拿到eventid后传给acknowledge_event即可批量消除。这套组合拳适合告警风暴时快速清理但别滥用——确认不等于解决该修的还得修。5.3 一个我坚持了很久的习惯这套 Docker 编排我用了快两年中间经历过 MySQL 数据卷权限丢失、Zabbix Server 升级后模板不兼容、告警脚本路径写错导致半夜没收到电话。从那以后我每次改完 compose 文件都强制走一遍「down → up -d → 看日志 → 登录 Web 确认 Server 状态 → 手动触发一个测试告警」的流程一步不省。尤其是docker compose down这一步很多人图省事用restart结果环境变量没重新加载排查半天以为是代码问题。希望这套拆解能帮你少走几个弯路把监控真正跑起来。本文还有配套的精品资源点击获取
返回列表