Docker部署Zabbix 7.0监控系统:完整实践与避坑指南

发布时间:2026/9/20 16:58:43
Docker部署Zabbix 7.0监控系统:完整实践与避坑指南 真正负责过监控系统的人应该都有这种经历需求方一张嘴就是“报警要准、图表要全、别老误报”可真到落地的时候最先花掉你半天时间的不是选型而是环境安装。Zabbix 是套组件多、依赖多、账号权限又绕的系统直接往物理机或虚拟机上装光是 MySQL 初始化、PHP-FPM 配置、前端文件权限、agent 与 server 之间各种端口策略就能把新人的热情耗掉一半。所以我才越来越倾向于用 Docker 部署 Zabbix把组件间通信和依赖关系先交给容器编排再集中精力解决监控本身的问题。这篇文章以 Zabbix 7.0 LTS 为例基于 docker compose 方式搭建一套完整的 Zabbix Server MySQL Web 前端 Agent 环境中间会穿插我在生产环境里实际踩过的坑。无论你是刚开始接触 Zabbix 的新手还是已经用原生方式部署过、想把它迁移到 Docker 里的老手都有可以直接抄的作业。1. 为什么绕了一圈最后还是回到 Zabbix Docker先交代一个背景判断Zabbix 不是那种让人眼前一亮的技术很多团队一开始看不上它嫌它界面老气、配置繁琐。但监控系统的核心价值从来不是界面好看而是“能不能在故障发生后的几十秒内把问题准确地告诉该知道的人”。这一点上Zabbix 的老练是实打实的。触发器表达式灵活告警升级机制成熟模板库庞大尤其是对服务器硬件、网络设备这类监控场景它天然就更贴近运维的习惯。至于为什么非要用 Docker 来部署我的体会是四个字环境隔离。Zabbix 的生产环境往往需要和公司其他服务共存不可能每次都给它单独准备一台机器。原生安装时MySQL、PHP、Nginx、Zabbix Server 全都装在同一台宿主机上版本冲突、目录污染、卸载不干净的问题层出不穷。而 Docker 把这些组件全部封装成独立容器主机层面只需要一个 Docker 引擎损坏了可以直接整套删掉重来对运维人员来说这是个巨大的确定性收益。Docker 部署还有一层隐性好处便于复现环境。公司里负责监控的人可能隔几个月就换一茬原生安装的 Zabbix 到了交接时新接手的人根本不知道当初是怎么装的、改过哪些配置文件。但如果项目根目录下有一个写清楚的 docker-compose.yml新人在半小时内就能理解整套架构出了问题也能通过 docker compose down docker compose up -d 快速恢复环境。不过我也要泼一盆冷水容器化不等于什么都放容器里。Zabbix 的数据库也就是 MySQL它所产生的数据必须放到宿主机挂载的 volume 或者外部存储中否则容器一删历史监控数据和配置就全没了。这个道理听起来简单我在早期测试环境里就吃过亏以为把数据目录映射出来就行结果因为宿主机磁盘满了MySQL 容器反复重启最后只能靠备份恢复。所以下面部署之前先把数据持久化的思路理清楚再开始动 docker compose。2. 部署前必须想清楚的三件事版本、规模、网络2.1 Zabbix 版本和数据库怎么选Zabbix 目前长期支持版本是 7.0官方支持周期会持续好几年新项目直接用 7.0 系列就行没必要从 6.0 或 6.4 重新起步。Docker 镜像方面官方在 Docker Hub 上发布了 zabbix-server-mysql、zabbix-server-pgsql、zabbix-web-nginx-mysql 等系列我们需要把 version 标签固定到具体版本比如 7.0-ubuntu-latest 或者更精确的 7.0.4-ubuntu1。不建议直接使用 latest 标签因为镜像一旦更新重新拉取时环境可能发生细微变化这在生产环境里是不必要的风险。数据库层面Zabbix 官方支持 MySQL 和 PostgreSQL 两套方案。我选择 MySQL 的理由其实没那么高级网上资料多、遇到问题好搜、团队里对 MySQL 的运维经验更成熟。如果你的团队已经具备 PostgreSQL 运维能力用 PG 完全没问题Zabbix 对两者的支持是同级别的。需要提醒的是Zabbix 7.0 对 MySQL 版本有最低要求使用 MySQL 8.0 是最稳妥的选择不要再用 5.7 了。2.2 机器规格和监控规模怎么匹配很多人一听“企业级”就觉得要上多高的配置其实 Zabbix 的资源消耗跟监控项数量强相关而不是简单和“设备台数”强相关。以中小规模为例几百台设备、每天产生几千到几万个监控项数据的场景4 核 8G 内存的虚拟机已经比较舒服。如果你只是在自己电脑上用 Docker 搭个测试环境2 核 4G 也能跑只不过前端加载会比较慢。真正吃资源的地方有两个一个是 Zabbix Server 内部缓存也就是配置缓存、历史数据缓存另一个是 MySQL 的写入。前者可以通过环境变量 ZBX_CACHESIZE 调整比如把默认的 8M 调到 128M能明显改善中大规模监控项的响应速度。后者就需要控制监控项的采集频率和数据保留周期我见过很多小型项目正是因为把监控项设成了每秒采集一次才导致数据库把磁盘塞满。2.3 端口规划和网络模式Zabbix 至少要关心三个端口组件端口作用Zabbix Server10051接收 agent 上报的数据Zabbix Agent10050被 server 主动拉取数据Web 前端8080/80/443浏览器访问管理界面在 Docker 部署中我比较推荐使用 bridge 网络加端口映射让容器之间通过 compose 网络内部的容器名互相访问。比如 Zabbix Server 在容器里访问数据库直接用 mysql 这个服务名而不是去解析宿主机的 IP。这样做的好处是隔离性好后续迁移也不容易断。如果网络环境比较复杂比如公司内部有防火墙、云主机有安全组部署之前就要先把 10051 和 10050 端口在安全组里放通。否则你会发现Zabbix Server 能启动、Web 前端也能打开但添加主机后一直显示“Waiting for first data”这时候通常不是 Zabbix 本身的问题而是防火墙把 agent 的 10050 端口挡住了。3. 手写 docker-compose.yml从零把整套服务拉起来下面这套 compose 文件是我在多个环境里验证过的适配 Zabbix 7.0 和 MySQL 8.0。先把目录建好比如 /opt/zabbix然后在这个目录下创建 docker-compose.yml。services: mysql: image: mysql:8.0 container_name: zabbix-mysql command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_bin environment: MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd MYSQL_ROOT_PASSWORD: root_pwd volumes: - ./zabbix-mysql-data:/var/lib/mysql networks: - zabbix-net restart: unless-stopped zabbix-server: image: zabbix/zabbix-server-mysql:7.0-ubuntu-latest container_name: zabbix-server environment: DB_SERVER_HOST: mysql DB_SERVER_PORT: 3306 MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd ZBX_STARTPOLLERS: 8 ZBX_CACHESIZE: 128M ports: - 10051:10051 volumes: - ./zabbix-server-externalscripts:/usr/lib/zabbix/externalscripts:ro - ./zabbix-server-alertscripts:/usr/lib/zabbix/alertscripts:ro networks: - zabbix-net depends_on: - mysql restart: unless-stopped zabbix-web: image: zabbix/zabbix-web-nginx-mysql:7.0-ubuntu-latest container_name: zabbix-web environment: ZBX_SERVER_HOST: zabbix-server DB_SERVER_HOST: mysql MYSQL_DATABASE: zabbix MYSQL_USER: zabbix MYSQL_PASSWORD: zabbix_pwd PHP_TZ: Asia/Shanghai ports: - 8080:8080 networks: - zabbix-net depends_on: - zabbix-server restart: unless-stopped zabbix-agent: image: zabbix/zabbix-agent:7.0-ubuntu-latest container_name: zabbix-agent environment: ZBX_SERVER_HOST: zabbix-server ZBX_HOSTNAME: DockerHost ports: - 10050:10050 networks: - zabbix-net depends_on: - zabbix-server restart: unless-stopped networks: zabbix-net: driver: bridge这个文件里有几个细节值得解释。第一MySQL 的 root 密码和 Zabbix 业务账号密码我都用明文写在了 compose 文件里这在内部测试环境没问题但生产环境建议用环境变量替换或者通过 Docker secret 管理。千万不要把生产环境密码推到 Git 仓库里。第二zabbix-server 挂载了两个目录externalscripts 和 alertscripts。前者是外部脚本的存放目录有些高级监控会用到比如通过外部脚本检查某个第三方接口后者是告警脚本目录如果后续要写自定义钉钉、企业微信、短信脚本放在这里最方便。提前把这些目录映射出来可以避免以后每次都要 docker cp 进容器。第三zabbix-web 的端口映射是 8080:8080避免和宿主机上可能存在的 Nginx 或 Apache 的 80 端口冲突。如果你确认宿主机 80 端口是空闲的也可以改成 80:8080这样访问时就不需要带端口号。启动之前先确保宿主机装了 Docker Engine 和 Docker Compose 插件。然后进入项目目录执行docker compose up -d第一次启动时MySQL 需要初始化数据目录Zabbix Server 还需要往数据库里导入 schema整个过程可能持续一两分钟。可以用下面的命令观察进度docker compose logs -f zabbix-server当看到类似Zabbix server started. Press CtrlC to exit.的日志时说明 Server 已经就绪。接着确认 Web 前端也能正常访问docker compose logs -f zabbix-web | grep -i start如果一切正常浏览器访问http://宿主机IP:8080就能看到 Zabbix 的登录界面。默认账号是 Admin默认密码是 zabbix登录后系统会提示你改密码。我的建议是第一次登录就立即改掉这个默认密码太出名了等被扫到再改就晚了。4. 登录界面之后添加主机、采集数据、手动确认告警4.1 改密码和语言设置Zabbix 7.0 默认界面语言是英文如果你更习惯中文可以在登录后点击右上角的人头像进入 User profile把 Language 改成“Chinese (zh_CN)”。中文化程度整体不错但有些专业术语翻译得比较生硬我实际使用中还是切回了英文这个看个人习惯。改完密码后建议顺手在 Administration - Users 里创建一个专用的运维账号而不是让大家共用 Admin。监控系统牵扯的权限其实很细有的同事只需要看面板不该给他触发器配置权限。Zabbix 支持用户组、角色权限划分前期不花这个时间后面出问题很难收场。4.2 把一台主机纳入监控现在 Zabbix Server 已经跑起来了但它只监控自己和那个容器化的 agent。接下来要把一台真实的业务服务器纳入监控这一节以 Linux 服务器为例。首先在被监控的服务器上安装 Zabbix Agent。不同发行版的安装命令不同但核心步骤一致安装软件包、修改 /etc/zabbix/zabbix_agentd.conf、启动服务。配置里最关键的两个参数ServerZabbix Server 的 IP ServerActiveZabbix Server 的 IP这里的 Server 表示允许哪个地址来主动采集ServerActive 表示 agent 要向哪个地址主动上报。很多新手只配了 Server结果画面上显示的“主动检查”通道一直不通就是因为漏了 ServerActive。如果被监控机和 Zabbix Server 之间有防火墙还要确认 10050 和 10051 两个端口都被放行。然后回到 Zabbix Web 界面进入 Data collection - Hosts点击 Create hostHost name填一个清晰可辨的名字比如 web-nginx-01Templates搜索并选择Linux by Zabbix agentInterfaces添加一个 Agent 接口IP 填被监控机的实际 IP端口默认 10050保存后系统会自动套用该模板里的所有监控项、触发器和图表。等 30 秒左右你会在 Hosts 列表里看到这台机器的 ZBX 图标变成绿色表示连通正常。进入 Monitoring - Latest data过滤主机名就能看到 CPU、内存、磁盘、网络等实时数据源源不断地进来。如果 ZBX 图标长期是红色或者监控项状态一直显示“Waiting for first data”我一般按下面这个顺序排查在被监控机上执行telnet zabbix-server-ip 10051确认主动上报通道通不通在 Zabbix Server 所在机器上执行telnet 被监控机 IP 10050确认主动采集通道通不通检查 zabbix_agentd.conf 里 Server 和 ServerActive 是否都配了最后再去 docker compose logs 里查 server 日志看有没有报错。把上面四步走完90% 的主机连不上问题都能定位到原因。4.3 告警产生后怎么手动确认和关闭Zabbix 里一个常见的操作需求是已经看到报警了正在处理中希望先在系统里做个标记让别人知道这个问题已经有人管或者在处理完后手动关掉这个告警。这个操作在 Zabbix 7.0 里叫 Acknowledge。操作路径很直接进入 Monitoring - Problems点击某条告警进入详情然后点击 Update 按钮。在弹出的面板里你可以填写处理备注比如“正在重启服务预计 5 分钟后恢复”。下方有一个状态选择如果希望同时关闭问题就选择 “Close problem”然后点击 Update。如果你只是想标记“有人看到了”不想关闭告警那就保持 Problem 状态不变只写备注和勾选确认选项即可。这个机制在生产环境里很有用比如半夜值班人员看到告警先确认一下后面的操作记录都会留痕交班时一目了然。这里提醒一句不要把“确认”和“关闭”混为一谈。确认指的是我已看到、我来处理关闭指的是问题已经解决。如果一个问题还没有真正恢复却被人直接关闭后续其他同事就不会再看到这条告警这会造成很危险的信息盲区。所以我在团队里立了规矩只有恢复后的告警或确认被误报的告警才准关闭。5. 告警链路打通邮件、钉钉 Webhook 与触发器的配合Zabbix 真正值钱的地方不在画图而在告警链路。下面我以钉钉机器人为例走一遍从媒介配置、用户绑定、动作规则到触发验证的完整流程。这套流程在 Zabbix 7.0 里已经非常成熟完全在 Web 界面完成不需要再写额外脚本。5.1 创建钉钉机器人并配置媒介先到钉钉群里添加一个自定义机器人。在群设置里找到“机器人” - “添加机器人” - “自定义”安全设置建议选“自定义关键词”关键词写一个不容易冲突的词比如“Zabbix监控”。钉钉对关键词有强制性要求如果发送的消息内容里不包含这个关键词请求会被钉钉 API 直接拒绝这是一个非常容易踩的坑。机器人创建完成后会得到一个 Webhook 地址形如https://oapi.dingtalk.com/robot/send?access_tokenxxxxxxxx然后进入 Zabbix 的 Administration - Media types找到名为“钉钉”的内置媒介类型按以下参数配置Webhook URL填上一步拿到的完整地址说明信息可以随便填但要写清楚这是哪个群的机器人配置好后直接点击“发送测试消息”按钮。如果成功钉钉群里马上会收到一条来自 Zabbix 的测试消息如果失败大概率是关键词没有命中。去 Webhook 地址后面加一个keywordZabbix监控并不是正解正确做法是确保测试消息的内容里包含你设置的关键词文字。5.2 给用户绑定媒介地址媒介类型创建好了还要把用户和这个媒介绑定起来。进入 Administration - Users点击你要接收告警的用户在 Media 选项卡里点击 AddType选择“钉钉”Send to这里虽然叫 Send to但钉钉机器人场景下主要用来区分多个媒介实例你可以填写群名或机器人备注When active默认全天都接收Severity默认全选保存后这个用户就具备了通过钉钉接收告警的通道。如果有多个人需要接收告警建议建一个用户组统一在用户组里给每个用户配置媒介这样后续人员调整时操作更集中。5.3 创建发送消息的 Action接下来是动作配置也就是把“满足什么条件的告警”和“执行什么通知动作”关联起来。进入 Alerts - Actions - Trigger actions点击 Create action。这里最关键的是条件设置。比如我一般会设置Trigger severity 大于等于 Warning当主机处于某个特定主机组比如“生产环境”才触发通知然后在 Operations 里配置操作内容项目配置Operation typeSend messageSend to users选择刚才配置过钉钉媒介的用户Send only to选择“钉钉”媒介Subject{TRIGGER.STATUS}: {TRIGGER.NAME}Message告警消息模板包含主机名、问题时间、当前值等Zabbix 的消息模板支持宏变量常用的有{HOST.NAME}、{TRIGGER.STATUS}、{TRIGGER.NAME}、{ITEM.VALUE}、{EVENT.DATE}、{EVENT.TIME}等。你完全可以根据需求自由组合不用死记硬背配置界面旁边就有宏列表可以查看。保存时留意一下告警条件里的“Maintenance”和“Event tags”如果维护模式下想暂时屏蔽某些告警可以在 Action 里加一个排除条件。经常有人问我为什么告警屏蔽不生效十有八九是动作里的条件没写全或者维护窗口的时间写错了排查时优先从这两个方向看。5.4 触发器配置和验证整条链路一个完整的告警链路最终要落到触发条件上。模板自带的触发器已经覆盖了很多常见场景比如 CPU 使用率过高、磁盘空间不足、服务不可达等。如果需要自定义可以在 Data collection - Hosts - 对应主机 - Triggers 里创建触发器。我举一个简单例子监控某台服务器上的 Nginx 进程是否存活。NameNginx process is not runningSeverityHighExpressionlast(/Linux by Zabbix agent proc.num[nginx]) 0这条表达式的意思是如果名为 nginx 的进程数量最近一次采集结果为 0就触发 High 级别告警。配置完触发器后最稳妥的验证方式是直接在生产环境之外做一次故障演练。比如手动停止一台测试机的 Nginx 服务然后观察Zabbix 是否在监控周期内捕捉到进程数变化Problems 列表是否出现对应的告警钉钉群是否在几秒到几十秒内收到告警消息恢复服务后告警是否自动关闭或需要手动确认。整个链路跑通一次之后你才敢放心地把监控告警交给 Zabbix 去扛。6. 长期跑下来维护和避坑才是重头戏部署只占 Zabbix 整个生命周期的小部分真正考验人的是后面几个月的维护。下面这几个方向是我在 Docker 部署 Zabbix 过程中觉得最值得投入时间的。6.1 数据库数据保留策略与手写清理Zabbix 默认把历史数据和趋势数据都存在 MySQL 里。如果默认保留策略一直开着监控项又很多数据库体积的增长会非常明显。Zabbix 里相关设置在 Administration - General - Housekeeping可以在里面调整 History 和 Trends 的保留天数。我常用的组合是历史数据保留 14 天趋势数据保留 365 天。配合 Zabbix 自带的 Housekeeper 自动清理任务基本不需要人为干预。不过要注意Housekeeper 只是删除数据库里过期记录它不会自动收缩表空间。MySQL 表文件一旦膨胀下去即使删了记录磁盘空间也不会自动释放。如果发现数据库文件特别大可以在低峰期对相关表执行 OPTIMIZE TABLE或者干脆规划好定时任务在每个月月底对 Zabbix 数据库做一次整理。6.2 备份优先级数据库永远排第一Docker 部署 Zabbix最大的风险就是以为容器本身是可备份的。容器确实可以 docker commit 打成镜像但这种方式既不优雅也不可靠真正需要备份的是 MySQL 数据目录和 compose 配置。官方推荐使用 mysqldump 逻辑备份我实际采用的命令大概是这样docker exec zabbix-mysql mysqldump --single-transaction -uzabbix -pzabbix_pwd zabbix | gzip /backup/zabbix_$(date %F).sql.gz用 --single-transaction 可以在不锁表的情况下做 InnoDB 的一致性备份在 Zabbix 这种持续写入场景下特别重要。一般我建议每天凌晨跑一次全量备份保留最近 30 天的备份文件。另外compose 文件、externalscripts、alertscripts 这些目录也要纳入备份范围因为里面很可能有你们自定义的监控脚本和告警脚本这些是代码资产丢了没法重新生成。6.3 镜像升级的正确姿势Zabbix 7.0 属于 LTS 版本小版本更新时直接拉新镜像升级通常风险可控。步骤很简单先修改 compose 文件里的镜像版本号然后执行docker compose pull docker compose up -d但有一点必须绷紧神经如果是从 6.x 跨大版本升级到 7.x先确认官方支持的升级路径。Zabbix 官方文档明确写了不能直接跨多个大版本跳级比如 5.0 直接升 7.0 是不被支持的必须先升到 6.0再升到 7.0。Docker 部署降低了环境安装成本但并没有跳过数据库结构升级这一步。每次升级前先把数据库备份好因为数据库结构变更脚本一旦执行很难无损回滚。我自己的习惯是升级前先看 Changelog重点看有没有破坏性变更然后在测试环境完整跑一遍升级流程最后才轮到生产环境操作。监控系统本身不产生业务收入但它一旦挂掉整个技术团队就变成了瞎子。6.4 容器资源限制和日志轮转Zabbix 几个容器跑久了之后最常见的隐患其实是日志。Docker 默认的 json-file 日志驱动不做轮转如果 zabbix-server 或 zabbix-web 长时间运行容器日志文件能膨胀到几个 GB。解决方法是在 /etc/docker/daemon.json 里加上日志轮转配置{ log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 } }修改后重启 Docker 服务新容器才会生效。已经存在的容器需要重新创建才能按新配置走所以这个设置最好在部署 Zabbix 之前就弄好。另外建议在生产环境的 compose 文件里给容器加上内存限制。MySQL 我一般限制到 4GZabbix Server 限制到 2GWeb 前端限制到 1G。这样做的好处是即使业务高峰期 Zabbix 处理不过来它最多把自己搞挂而不会把宿主机拖垮让同机的其他服务跟着遭殃。Docker 的 mem_limit 就是在服务定义里加一个字段行数不多但非常值得写进去。6.5 扩展场景GPU 监控、Oracle 监控等Zabbix 的能力边界其实比很多人想象中大。比如有位朋友问我能不能拿 Docker 里的 Zabbix 去监控 Windows 服务器上的 GPU 利用率答案是完全可以但要注意两点一是 Windows 上要装对应配套的 agent二是 GPU 指标通常需要额外用性能计数器或 nvidia-smi 脚本形式接入。Zabbix 的自定义监控项机制很灵活Linux 下可以写外部脚本Windows 下可以通过性能计数器采集这些都是现成功能。再比如监控 Oracle 数据库Zabbix 官方提供了专门的数据库监控模板可以采集实例状态、表空间使用率、会话数、慢查询等指标。部署方式就是在被监控的 Oracle 服务器上装 agent再配置好数据库账号和模板即可和监控一台普通 Linux 主机的思路没有本质区别。Zabbix 不适合拿来替代 APM 或链路追踪这类专门工具但作为基础设施层面的“总值班班长”它的生态已经足够覆盖绝大多数常规需求。最后分享一个小教训也是我这套方案里认知最深的一次我第一次用 Docker 部署 Zabbix 的时候Web 界面死活打不开查了半天发现是宿主机的防火墙把 8080 端口挡了。当时既生气又觉得好笑因为如果一开始就在端口规划时把安全组和防火墙全部想清楚这几十分钟完全可以省下来。所以这篇里我在部署前花了不少篇幅讲端口和网络就是希望看到这篇文章的人能少走这段弯路。Zabbix 的世界里大多数“玄学故障”背后都是最简单不过的网络或者权限问题。