# ============================================================================= # Zabbix 7.4.16 单机 Docker Compose —— 优化/低坑版 # 用法(先备份原文件): # cd /opt/zabbix # cp docker-compose.yaml docker-compose.yaml.bak_$(date +%s) # docker compose -f docker-compose.new.yaml config -q # 先校验语法 # docker compose -f docker-compose.new.yaml up -d # 重建生效 # 说明: # - 镜像锁定精确版本,避免 `pull` 后被动升级。 # - 密码/时区均可用 .env 覆盖,默认值与原文件一致,可直接替换。 # - 缓存按 75k 项 / 186 台交换机的实测用量重估(见说明文档)。 # ============================================================================= services: zabbix-mysql: image: mysql:8.0.43 container_name: zabbix-mysql command: - --character-set-server=utf8mb4 - --collation-server=utf8mb4_bin - --innodb-buffer-pool-size=1G - --innodb-file-per-table=1 - --log-bin-trust-function-creators=1 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-CobcoIT132} MYSQL_DATABASE: ${MYSQL_DATABASE:-zabbix} MYSQL_USER: ${MYSQL_USER:-zabbix} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-CobcoIT132} TZ: ${TZ:-UTC} volumes: - /opt/zabbix/zabbix-server/mysql_data:/var/lib/mysql networks: zabbix: ipv4_address: 192.168.87.22 restart: unless-stopped stop_grace_period: 1m logging: driver: json-file options: max-size: "10m" max-file: "3" healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"] interval: 10s timeout: 5s retries: 10 start_period: 40s zabbix-server: image: zabbix/zabbix-server-mysql:ubuntu-7.4.16 container_name: zabbix-server networks: zabbix: ipv4_address: 192.168.87.21 ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000 # 仅保留实际需要的权限:NET_RAW 供 fping(ICMP 监控),SYS_NICE 供进程优先级。 # 不再使用 privileged:true / cap_add:ALL(过度授权、有安全风险)。 # 若完全不做 ICMP ping 监控,可删除整个 cap_add 段。 cap_add: - NET_RAW - SYS_NICE sysctls: - net.ipv4.ip_local_port_range=1024 65000 - net.ipv4.conf.all.accept_redirects=0 - net.ipv4.conf.all.secure_redirects=0 - net.ipv4.conf.all.send_redirects=0 restart: unless-stopped stop_grace_period: 30s logging: driver: json-file options: max-size: "10m" max-file: "3" environment: DB_SERVER_HOST: zabbix-mysql MYSQL_DATABASE: ${MYSQL_DATABASE:-zabbix} MYSQL_USER: ${MYSQL_USER:-zabbix} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-CobcoIT132} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-CobcoIT132} TZ: ${TZ:-UTC} # ---- 缓存:按 75k 项、186 台交换机的实测用量重新定容 ---- ZBX_CACHESIZE: 512M # 配置缓存 实测 12%(~123M),512M 留约 4 倍余量 ZBX_VALUECACHESIZE: 128M # 值缓存 实测 1.1%(~12M) ZBX_TRENDCACHESIZE: 64M # 趋势缓存 实测 0.39%(~4M),原 1G 严重超配 ZBX_HISTORYCACHESIZE: 64M # 历史缓存 实测≈0 ZBX_HISTORYINDEXCACHESIZE: 16M # 历史索引 实测 0.24%(~77K) ZBX_TRENDFUNCTIONCACHESIZE: 16M # 趋势函数缓存,默认 4M 已足 # ---- 进程数:186 台交换机以 1 次 walk/台 轮询,30 个 SNMP poller 实测 busy≈3% ---- ZBX_STARTSNMPPOLLERS: 30 ZBX_STARTLLDWORKERS: 10 # 大批 LLD 发现更快 ZBX_STARTPREPROCESSORS: 5 ports: - '10051:10051' volumes: - /opt/zabbix/zabbix-server/data:/data - /opt/zabbix/zabbix-server/data/alertscripts:/usr/lib/zabbix/alertscripts depends_on: zabbix-mysql: condition: service_healthy zabbix-web-nginx-mysql: image: zabbix/zabbix-web-nginx-mysql:ubuntu-7.4.16 container_name: zabbix-webservice networks: zabbix: ipv4_address: 192.168.87.20 restart: unless-stopped logging: driver: json-file options: max-size: "10m" max-file: "3" environment: DB_SERVER_HOST: zabbix-mysql MYSQL_DATABASE: ${MYSQL_DATABASE:-zabbix} MYSQL_USER: ${MYSQL_USER:-zabbix} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-CobcoIT132} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-CobcoIT132} ZBX_SERVER_HOST: zabbix-server TZ: ${TZ:-UTC} PHP_TZ: ${TZ:-UTC} volumes: - /opt/zabbix/zabbix-server/web:/data # 插件目录随仓库一起走:默认用 compose 同级的 ./web-modules, # 已有环境可用 WEB_MODULES_DIR 覆盖为绝对路径(如 /opt/zabbix/zabbix-server/web-modules)。 - ${WEB_MODULES_DIR:-./web-modules}:/usr/share/zabbix/modules - /opt/zabbix/zabbix-server/fonts/simkai.ttf:/usr/share/zabbix/assets/fonts/DejaVuSans.ttf depends_on: zabbix-mysql: condition: service_healthy zabbix-server: condition: service_started # --------------------------------------------------------------------------- # 首次部署自动登记 WecomCenter 模块(幂等):让全新 Docker 环境 up 起来后插件 # 就已“启用”,无需手动去 Administration → General → Modules 点启用。 # moduleid 在 Zabbix 里不是自增列,这里取 MAX+1 显式写入。 # --------------------------------------------------------------------------- wecom-module-init: image: mysql:8.0.43 container_name: zabbix-wecom-module-init restart: "no" depends_on: zabbix-mysql: condition: service_healthy zabbix-server: condition: service_started environment: MYSQL_PWD: ${MYSQL_ROOT_PASSWORD:-CobcoIT132} MYSQL_DATABASE: ${MYSQL_DATABASE:-zabbix} entrypoint: ["/bin/sh", "-c"] command: - | set -e HOST=zabbix-mysql DB="$${MYSQL_DATABASE}" echo "[wecom-init] waiting for MySQL at $$HOST ..." until mysql -h "$$HOST" -uroot -e "SELECT 1" >/dev/null 2>&1; do sleep 2; done echo "[wecom-init] waiting for Zabbix schema (module table) ..." i=0 while [ "$$i" -lt 150 ]; do if mysql -h "$$HOST" -uroot "$$DB" -e "SELECT 1 FROM module LIMIT 1" >/dev/null 2>&1; then break fi sleep 2 i=$$((i + 1)) done if ! mysql -h "$$HOST" -uroot "$$DB" -e "SELECT 1 FROM module LIMIT 1" >/dev/null 2>&1; then echo "[wecom-init] ERROR: Zabbix schema/module table not ready after 300s" >&2 exit 1 fi mysql -h "$$HOST" -uroot "$$DB" <<'SQL' SET @nid := (SELECT COALESCE(MAX(moduleid), 0) + 1 FROM module); INSERT INTO module (moduleid, id, relative_path, status, config) SELECT @nid, 'wecom_center', 'modules/WecomCenter', 1, '[]' FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM module WHERE id = 'wecom_center'); CREATE TABLE IF NOT EXISTS l2_topology_history ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, ts BIGINT UNSIGNED NOT NULL, captured_at DATETIME NOT NULL, stats TEXT NOT NULL, snapshot MEDIUMBLOB NOT NULL, PRIMARY KEY (id), KEY idx_l2_ts (ts) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; CREATE TABLE IF NOT EXISTS l2_topology_config ( id TINYINT UNSIGNED NOT NULL, config LONGTEXT NOT NULL, updated DATETIME NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; SQL echo "[wecom-init] module 'wecom_center' ensured (enabled) + L2 tables ensured." networks: - zabbix logging: driver: json-file options: max-size: "5m" max-file: "2" networks: zabbix: ipam: config: - subnet: 192.168.87.0/24