简介:这份资源面向需要在 Linux 服务器上快速搭建监控平台的运维人员与开发者,提供用 Docker 部署 Zabbix 的完整代码包,解决传统安装方式依赖多、配置繁琐的问题。压缩包共 5 个文件,约 11KB,以 docker-compose.yml 为核心编排文件,配合 README.md 说明文档、index.html 页面、.gitignore 与 .inscode 配置,覆盖容器定义、环境变量与端口映射等关键环节,结构精简便于直接复用。资源同时给出两种部署思路:一是通过 Compose 一键启动 Zabbix 服务、MySQL 数据库与前端,二是借助宝塔面板已有数据库创建 Zabbix 容器,读者可结合自身环境选择。目前已有 46 人学习,适合希望快速落地 CPU、内存、磁盘与网络流量监控及报警能力的初、中级运维人员参考。
1. 从一台干净的 Linux 主机说起:Docker 装 Zabbix 到底省了什么
如果你手上有一台刚装好系统的 Linux 主机,想跑一套 Zabbix 监控,传统路子是先装 MySQL、再编译 PHP、配 Nginx、调 php.ini 的时区与内存限制,最后还要处理 SELinux 和防火墙。这套流程走下来,半天时间基本就没了,而且换一台机器还得重来一遍。Docker 装 Zabbix 的核心价值,就是把这套「环境依赖链」压成几个容器,让数据库、服务端、前端各跑各的,互不污染。这份代码包围绕的正是这个场景:用容器编排的方式,把 Zabbix 的 MySQL 后端、zabbix-server、zabbix-web 三个角色拆开部署,适合运维、后端开发、以及需要快速搭一套监控环境做验证的从业者。它不要求你精通 PHP 编译,但要求你能看懂 compose 文件里的端口、卷和环境变量——这三样才是后面排错的主战场。
2. 拆开 compose 文件:三个容器各自扛什么活
2.1 为什么是 MySQL 而不是 PostgreSQL
Zabbix 官方对两种数据库都支持,但社区里绝大多数部署示例、迁移脚本、备份工具都是围绕 MySQL 写的。这份代码包选 MySQL 作为后端,主要原因是生态成熟:mysqldump 备份、主从复制、慢查询日志分析,这些运维动作在 MySQL 上资料最多。如果你所在团队已经有 PostgreSQL 的运维经验,换成 pgsql 也能跑,但要注意 Zabbix 对两种数据库的字符集要求不同——MySQL 必须用 utf8mb4,PostgreSQL 则要留意排序规则,否则中文主机名会出现乱码。
容器拆分的逻辑是这样的:数据库容器只负责存数据,不对外暴露端口;zabbix-server 容器通过内部网络连数据库,对外暴露 10051 端口接收 agent 上报;zabbix-web 容器跑 Nginx + PHP-FPM,对外暴露 8080 或 80 端口给浏览器访问。三者通过 Docker 自定义网络通信,容器名就是主机名,不需要记 IP。
2.2 一份可直接抄的 compose 骨架
下面这份 compose 文件是代码包里最核心的部分,我把它拆成三段来看。先看数据库段:
services: mysql-server: image: mysql:8.0 container_name: zabbix-mysql command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_bin - --default-authentication-plugin=mysql_native_password environment: MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd_2024 MYSQL_ROOT_PASSWORD: root_pwd_2024 volumes: - ./data/mysql:/var/lib/mysql networks: - zbx-net这里有几个参数值得说清楚。--character-set-server=utf8mb4和--collation-server=utf8mb4_bin是 Zabbix 的硬性要求,排序规则必须是_bin结尾,用_general_ci会在建表阶段报错。--default-authentication-plugin=mysql_native_password是为了兼容旧版客户端,MySQL 8 默认用 caching_sha2_password,某些 Zabbix 版本连不上。volumes把数据目录挂到宿主机,容器删了数据还在,这是后悔药。
再看服务端段:
zabbix-server: image: zabbix/zabbix-server-mysql:alpine-6.4-latest container_name: zabbix-server environment: DB_SERVER_HOST: mysql-server MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd_2024 ports: - "10051:10051" depends_on: - mysql-server networks: - zbx-netDB_SERVER_HOST填的是容器名mysql-server,不是 localhost,也不是 127.0.0.1。这是新手最容易翻车的地方——在容器里写 localhost 等于指向容器自己,数据库根本不在那。depends_on只保证启动顺序,不保证数据库已经初始化完成,所以第一次启动时 server 容器可能会重试几次才连上,这是正常现象。
最后是前端段:
zabbix-web: image: zabbix/zabbix-web-nginx-mysql:alpine-6.4-latest container_name: zabbix-web 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 ports: - "8080:8080" depends_on: - mysql-server - zabbix-server networks: - zbx-net networks: zbx-net: driver: bridgePHP_TZ: Asia/Shanghai必须设,否则前端图表的时间轴会差 8 小时,看监控数据时你会怀疑人生。端口映射8080:8080左边是宿主机端口,右边是容器内端口,如果宿主机 8080 被占,改成8081:8080即可,容器内部不用动。
2.3 启动顺序与初始化时机
把上面三段拼成一个完整的docker-compose.yml,放到一个空目录里,然后执行:
docker compose up -d这条命令会按依赖顺序拉起三个容器。第一次执行时,MySQL 需要初始化数据目录并导入 Zabbix 的初始表结构,这个过程大概持续 30 到 60 秒。你可以用下面这条命令观察 server 容器的日志:
docker logs -f zabbix-server当看到database is up and running或者starting zabbix server之类的字样,说明数据库连接已经通了。如果一直刷cannot connect to database,先别急着重启,等两分钟再看——MySQL 初始化慢是常态。
3. 从容器到浏览器:把监控面板跑起来的完整链路
3.1 首次登录与初始配置
三个容器都起来之后,浏览器访问http://你的主机IP:8080,会看到 Zabbix 的安装向导。这里有个细节:向导第一步是选语言,选中文之后点下一步,会检查 PHP 环境和数据库连接。如果数据库那一步报错,八成是 compose 里的密码和实际不一致,或者 MySQL 还没初始化完。
向导走完会要求你登录,默认账号是Admin,密码是zabbix,注意 A 是大写。登录后第一件事是改密码,第二件事是检查Administration → General → Timezone,确认时区是Asia/Shanghai。这两步不做,后面看数据全是错的。
3.2 添加第一台被监控主机
Zabbix 装好只是空壳,得往里加主机才有数据。假设你要监控另一台 Linux 机器,在那台机器上装 zabbix-agent:
# 在目标主机上执行 docker run -d \ --name zabbix-agent \ --restart unless-stopped \ -e ZBX_HOSTNAME="web-server-01" \ -e ZBX_SERVER_HOST="你的Zabbix服务器IP" \ -p 10050:10050 \ zabbix/zabbix-agent:alpine-6.4-latestZBX_HOSTNAME是这台主机在 Zabbix 里显示的名字,必须和后面在 Web 界面里填的「主机名称」完全一致,否则 agent 上报的数据会被拒绝。ZBX_SERVER_HOST填 Zabbix 服务端的 IP,不是容器名,因为 agent 跑在另一台宿主机上。
然后在 Web 界面Configuration → Hosts → Create host,主机名称填web-server-01,接口选 Agent,IP 填目标主机 IP,端口 10050。模板选Linux by Zabbix agent,保存后等一分钟,Monitoring → Latest data里就能看到 CPU、内存、磁盘的数据了。
3.3 数据持久化与备份策略
容器化部署最大的风险是数据丢失。compose 里已经把 MySQL 数据目录挂到了./data/mysql,但光挂载不够,还得定期备份。我一般用 cron 跑一条 mysqldump:
#!/bin/bash # 每天凌晨 3 点备份 Zabbix 数据库 BACKUP_DIR="/backup/zabbix" DATE=$(date +%Y%m%d) docker exec zabbix-mysql mysqldump -uzabbix -pzabbix_pwd_2024 zabbix > ${BACKUP_DIR}/zabbix_${DATE}.sql # 只保留最近 7 天 find ${BACKUP_DIR} -name "zabbix_*.sql" -mtime +7 -delete这条脚本的关键是docker exec进容器执行 mysqldump,而不是在宿主机上装 mysql 客户端。备份文件落在宿主机目录,容器重建也不影响。恢复的时候用docker exec -i zabbix-mysql mysql -uzabbix -pzabbix_pwd_2024 zabbix < 备份文件.sql即可。
4. 避坑排查:容器化 Zabbix 最常见的五个翻车现场
4.1 前端报「Database error」但 server 日志正常
现象是浏览器打开 8080 端口显示数据库连接错误,但docker logs zabbix-server里没有任何报错。原因通常是 zabbix-web 容器里的DB_SERVER_HOST写成了 localhost 或者 IP,而不是容器名mysql-server。解决方法是进 web 容器检查环境变量:docker exec zabbix-web env | grep DB_,确认指向的是容器名。如果 compose 里写对了但还是报错,检查三个容器是否在同一个 network 里,用docker network inspect zbx-net看成员列表。
4.2 中文主机名显示为问号
现象是添加了中文名称的主机后,Web 界面显示乱码或问号。原因是 MySQL 的字符集不是 utf8mb4,或者排序规则不是utf8mb4_bin。这个问题在容器启动后再改很麻烦,因为表已经建好了。解决办法是删掉./data/mysql目录,修改 compose 里的字符集参数,重新docker compose up -d。所以第一次部署时就要把字符集写对,别等数据进去了再改。
4.3 图表时间比实际时间差 8 小时
现象是 Latest data 里的时间戳比当前时间早 8 小时,或者图表横轴对不上。原因是 PHP 容器的时区没设。检查docker exec zabbix-web date,如果输出 UTC 时间,说明PHP_TZ没生效。在 compose 的 zabbix-web 段加上PHP_TZ: Asia/Shanghai,然后docker compose restart zabbix-web。注意 MySQL 容器和 server 容器的时区也要确认,虽然它们不直接渲染图表,但日志时间戳会受影响。
4.4 10051 端口通了但 agent 数据上不来
现象是 Zabbix 服务端 10051 端口在监听,agent 也显示运行中,但 Web 界面里主机一直是灰色的「ZBX」图标。原因可能是 agent 的ZBX_HOSTNAME和 Web 界面里的主机名称不一致,或者服务端的防火墙没放行 10050 端口。先在 agent 所在机器上telnet Zabbix服务器IP 10051测试连通性,再检查 Web 界面Configuration → Hosts里主机名称是否和 agent 环境变量完全一致,包括大小写。
4.5 容器重启后数据全没了
现象是docker compose down之后再up,之前配置的主机、模板、告警全消失。原因是 compose 里没有配 volumes,MySQL 数据存在容器内部,容器一删数据就没了。检查 compose 文件里 mysql-server 段是否有./data/mysql:/var/lib/mysql这行。如果已经配了但还是丢,确认./data/mysql目录的权限,MySQL 容器里的 mysql 用户需要写权限,宿主机上这个目录的属主最好是 999:999 或者 1000:1000。
5. 进阶技巧:用环境变量批量管理多套 Zabbix 实例
当你需要同时跑测试环境和生产环境两套 Zabbix 时,复制两份 compose 文件改端口是最笨的办法。更省事的做法是用.env文件加变量替换。在 compose 文件同级目录建一个.env:
# .env 文件 ZBX_WEB_PORT=8080 ZBX_SERVER_PORT=10051 MYSQL_ROOT_PWD=root_pwd_2024 MYSQL_ZBX_PWD=zabbix_pwd_2024 DATA_DIR=./data然后把 compose 里的硬编码值换成变量:
ports: - "${ZBX_WEB_PORT}:8080" environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PWD} MYSQL_PASSWORD: ${MYSQL_ZBX_PWD} volumes: - ${DATA_DIR}/mysql:/var/lib/mysql这样测试环境用一份.env,生产环境用另一份,compose 文件本身不用动。启动时docker compose --env-file .env.prod up -d就能指定不同的配置文件。这个技巧在需要横向扩展多套监控实例时特别有用,比如给不同业务线各一套 Zabbix,互不干扰。
验证部署是否成功,我一般走这三步:先docker compose ps看三个容器是不是都 Up;再curl -I http://localhost:8080看前端返回 200;最后登录 Web 界面看Reports → System information,确认 server 运行时间和数据库大小正常。三步都过,这套环境就算稳了。
从那以后我每次部署容器化的中间件,都强制先确认三件事:数据卷挂没挂、时区设没设、容器名和连接地址对不对。这三样不出问题,剩下的都是小修小补。希望帮到你。
本文还有配套的精品资源,点击获取