How to Build a Full‑Featured Zabbix Monitoring Platform with Docker Compose
This step‑by‑step guide shows how to choose Zabbix over other monitoring tools, deploy a complete Zabbix stack with Docker Compose, configure agents on Linux and Windows, set up auto‑discovery, alerts (email, WeChat, escalation), use proxies for distributed monitoring, and optimize performance for enterprise environments.
Core Architecture
Zabbix follows a client/server (C/S) model with four main components:
Zabbix Server : receives data, processes triggers, stores history, and sends alerts.
Zabbix Agent : installed on monitored hosts; supports active and passive modes.
Zabbix Proxy : optional distributed collector that forwards data to the server (useful for multi‑site deployments).
SNMP devices : monitored via SNMP without agents.
One‑Click Deployment with Docker Compose
Create a docker-compose.yml file that defines MySQL, Zabbix Server, Web UI, and Agent services. Example:
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: zabbix-mysql
command:
- mysqld
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_bin
- --default-authentication-plugin=mysql_native_password
environment:
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_password
MYSQL_ROOT_PASSWORD: root_password
volumes:
- zabbix_mysql_data:/var/lib/mysql
networks:
- zabbix-net
restart: unless-stopped
zabbix-server:
image: zabbix/zabbix-server-mysql:ubuntu-7.0-latest
container_name: zabbix-server
environment:
DB_SERVER_HOST: mysql
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_password
MYSQL_ROOT_PASSWORD: root_password
ZBX_CACHESIZE: 128M
ZBX_STARTPOLLERS: 10
ZBX_STARTPINGERS: 5
ports:
- "10051:10051"
volumes:
- zabbix_server_alertscripts:/usr/lib/zabbix/alertscripts
- zabbix_server_externalscripts:/usr/lib/zabbix/externalscripts
networks:
- zabbix-net
depends_on:
- mysql
restart: unless-stopped
zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:ubuntu-7.0-latest
container_name: zabbix-web
environment:
ZBX_SERVER_HOST: zabbix-server
DB_SERVER_HOST: mysql
MYSQL_DATABASE: zabbix
MYSQL_USER: zabbix
MYSQL_PASSWORD: zabbix_password
PHP_TZ: Asia/Shanghai
ports:
- "8080:8080"
networks:
- zabbix-net
depends_on:
- mysql
- zabbix-server
restart: unless-stopped
zabbix-agent:
image: zabbix/zabbix-agent:ubuntu-7.0-latest
container_name: zabbix-agent
environment:
ZBX_HOSTNAME: "Zabbix server"
ZBX_SERVER_HOST: zabbix-server
ports:
- "10050:10050"
networks:
- zabbix-net
depends_on:
- zabbix-server
restart: unless-stopped
volumes:
zabbix_mysql_data:
zabbix_server_alertscripts:
zabbix_server_externalscripts:
networks:
zabbix-net:
driver: bridgeStart all services:
# Run in background
docker-compose up -d
# View server logs
docker-compose logs -f zabbix-serverAccess the web UI at http://SERVER_IP:8080 with default credentials Admin / zabbix. Change the password after first login.
Agent Deployment and Configuration
Linux
Install the official Zabbix repository and the latest Agent2 package:
# Ubuntu/Debian
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_7.0-1+ubuntu$(lsb_release -rs)_all.deb
dpkg -i zabbix-release_7.0-1+ubuntu$(lsb_release -rs)_all.deb
apt update
apt install zabbix-agent2 -y
# CentOS/RHEL
rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rhel/8/x86_64/zabbix-release-7.0-1.el8.noarch.rpm
dnf clean all && dnf makecache
dnf install zabbix-agent2 -yEdit /etc/zabbix/zabbix_agent2.conf (example values):
# Server IP(s)
Server=192.168.1.100
# Active server for active checks
ServerActive=192.168.1.100
# Hostname must match the name used in Zabbix UI
Hostname=web-server-01
# Debug level (1=error, 3=debug)
DebugLevel=3
# Allow custom user parameters
UnsafeUserParameters=1Enable and start the agent:
systemctl enable zabbix-agent2 --now
systemctl status zabbix-agent2Windows
Download the MSI installer from the Zabbix download page, run the installer, set the Server IP and Hostname, then start the Zabbix Agent 2 service. Configuration file is C:\Program Files\Zabbix Agent 2\zabbix_agent2.conf with the same parameters as Linux.
Monitoring Configuration in the Web UI
Add hosts, assign interfaces, link templates (e.g., "Linux by Zabbix agent"), and configure host groups. Use auto‑discovery rules for bulk resources such as disk partitions ( vfs.fs.discovery) or Docker containers (custom script docker_discovery.py).
Auto‑Discovery Example – Disk Partitions
Create a discovery rule with key vfs.fs.discovery and filter {#FSTYPE}=ext4|xfs|btrfs to automatically add items for usage and free space.
Auto‑Discovery Example – Docker Containers
#!/usr/bin/env python3
import subprocess, json
def discover_containers():
result = subprocess.run(['docker','ps','--format','{{.Names}}'], capture_output=True, text=True)
containers = result.stdout.strip().split('
')
data = [{'{#CONTAINER}': c} for c in containers if c]
return json.dumps({'data': data})
if __name__ == '__main__':
print(discover_containers())Make the script executable ( chmod +x /usr/lib/zabbix/externalscripts/docker_discovery.py) and use key docker.containers.discovery in a discovery rule.
Alerting Configuration
Email Alerts
Install mailutils on the server and create a script /usr/lib/zabbix/alertscripts/send_email.sh:
#!/bin/bash
TO="$1"
SUBJECT="$2"
BODY="$3"
echo "$BODY" | mail -s "$SUBJECT" "$TO"Make it executable ( chmod +x /usr/lib/zabbix/alertscripts/send_email.sh) and create a media type of type Script named "Email" that calls the script with parameters {ALERT.SENDTO}, {ALERT.SUBJECT}, {ALERT.MESSAGE}. Assign the media to users.
WeChat (Enterprise WeChat) Alerts
Create /usr/lib/zabbix/alertscripts/wechat.py:
#!/usr/bin/env python3
import sys, requests, json
CORPID='your_corpid'
SECRET='your_secret'
AGENTID=1000002
def get_token():
url=f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={CORPID}&corpsecret={SECRET}'
return requests.get(url).json()['access_token']
def send_message(user, subject, message):
token=get_token()
url=f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}'
data={
"touser": user,
"msgtype": "text",
"agentid": AGENTID,
"text": {"content": f"【{subject}】
{message}"}
}
return requests.post(url, json=data).json()
if __name__=='__main__':
user=sys.argv[1]
subject=sys.argv[2]
message=sys.argv[3]
print(send_message(user, subject, message))Register a script media type "WeChat" that calls wechat.py with the same three parameters.
Escalation (Alarm Upgrade)
Create an action with multiple steps: Step 1 (0‑30 min) notifies on‑call staff, Step 2 (30‑60 min) notifies a senior engineer, Step 3 (after 60 min) notifies the technical director and triggers a phone call.
Distributed Monitoring with Zabbix Proxy
Deploy a proxy using Docker Compose ( docker-compose-proxy.yml) and configure it to forward data to the central server:
version: '3.8'
services:
zabbix-proxy:
image: zabbix/zabbix-proxy-sqlite3:ubuntu-7.0-latest
container_name: zabbix-proxy
environment:
ZBX_PROXYMODE: 0 # 0 = active mode (recommended)
ZBX_HOSTNAME: proxy-beijing
ZBX_SERVER_HOST: 192.168.1.100 # central server IP
ZBX_CONFIGFREQUENCY: 300
ports:
- "10051:10051"
volumes:
- zabbix_proxy_data:/var/lib/zabbix
restart: unless-stopped
volumes:
zabbix_proxy_data:Start it with docker-compose -f docker-compose-proxy.yml up -d. The proxy collects data from local agents and synchronizes with the server, enabling multi‑site monitoring without exposing the server directly.
Performance Tuning
Server Settings
# Example /etc/zabbix/zabbix_server.conf adjustments
CacheSize=256M
HistoryCacheSize=64M
TrendCacheSize=16M
StartPollers=20
StartPollersUnreachable=5
StartPingers=10
StartDiscoverers=5Database Optimizations
Use partitioned tables for history and history_uint (daily or monthly).
Delete data older than 90 days and run OPTIMIZE TABLE regularly.
Prefer Unix socket connections when DB and server share a host.
Item Interval Recommendations
Critical metrics (CPU, memory): 30 s – 1 min.
Normal metrics (disk usage): 5 min.
Trend metrics (traffic): 30 min.
Keep per‑host items under 200.
Common Monitoring Templates
Import ready‑made templates from the Zabbix Template Marketplace for MySQL, Redis, Nginx, AWS, Azure, etc., or add custom UserParameter definitions such as:
# MySQL
UserParameter=mysql.status[*],mysqladmin -umonitor -ppassword extended-status | awk '/$1/{print $$4}'
UserParameter=mysql.ping,mysqladmin -umonitor -ppassword ping | grep -c alive
# Redis
UserParameter=redis.info[*],redis-cli -h localhost -p 6379 INFO $1 | grep -w $2 | cut -d: -f2
UserParameter=redis.ping,redis-cli -h localhost ping | grep -c PONG
# Nginx (requires status page)
UserParameter=nginx.active,curl -s http://127.0.0.1/nginx_status | awk '/Active/{print $3}'
UserParameter=nginx.accepts,curl -s http://127.0.0.1/nginx_status | awk 'NR==3{print $1}'Dashboard Customization
Create a dashboard with widgets such as "Problems by severity", "Top hosts by CPU/Memory", trend graphs, geo‑map of hosts, and service status. Add SLA reports for critical services using Zabbix's SLA management.
Operational Recommendations
Start with a small set of critical hosts and expand gradually.
Set meaningful trigger thresholds to avoid alert fatigue; aim for <5 min response for high‑severity alerts.
Review and clean unused items quarterly.
Back up the Zabbix database and configuration files regularly.
Leverage official documentation and the Template Marketplace for quick, reliable integrations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Xiao Liu Lab
An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
