1. Introduccion
Esta guia monta un entorno de monitorizacion con Zabbix en el que el servidor (server + frontend + base de datos) corre en Docker, mientras que los tres equipos a monitorizar — el propio host Docker, un Ubuntu Server y un Windows 11 — llevan el agente Zabbix instalado de forma nativa, tal y como se haria en un entorno real. No todo va dentro de contenedores: el objetivo es replicar el patron mas habitual en produccion, donde el servidor de monitorizacion es una pieza centralizada y los agentes viven en cada endpoint, incluido el propio servidor que aloja Zabbix.
2. Variables de esta guia
Todos los bloques de configuracion usan los siguientes marcadores en MAYUSCULAS. Sustituyelos por los valores reales del entorno donde se aplique esta guia.
| Marcador | Que es | Donde se obtiene |
|---|---|---|
IP_HOST_DOCKER | IP del host Linux donde corre el stack de Zabbix con Docker | La interfaz de red de ese host |
MYSQL_PASSWORD | Contraseña del usuario zabbix en la base de datos | Se define en /docker/zabbix/.env, no en el docker-compose.yml (paso 5) |
MYSQL_ROOT_PASSWORD | Contraseña root de MySQL dentro del contenedor | Se define en /docker/zabbix/.env, no en el docker-compose.yml (paso 5) |
HOSTNAME_DOCKER | Nombre con el que el propio host Docker se identifica ante Zabbix como agente | Lo defines tu; debe coincidir exacto en agente y frontend |
IP_AGENTE_UBUNTU | IP del Ubuntu Server donde se instala el agente | ip a en ese equipo |
HOSTNAME_UBUNTU | Nombre con el que ese agente se identifica ante Zabbix | Lo defines tu; debe coincidir exacto en agente y frontend |
IP_AGENTE_WINDOWS | IP del equipo Windows 11 donde se instala el agente | ipconfig en ese equipo |
HOSTNAME_WINDOWS | Nombre con el que ese agente se identifica ante Zabbix | Lo defines tu; debe coincidir exacto en agente y frontend |
3. Arquitectura y flujo
Zabbix soporta dos formas de recoger datos, y no son intercambiables sin mas: cambia quien inicia la conexion. Esta guia usa checks activos como modelo principal (es el que se sigue en el resto de los pasos), porque es el habitual en este canal: el firewall solo se abre en el servidor, nunca en el endpoint.
[HOST DOCKER] [UBUNTU SERVER] [WINDOWS 11]
zabbix-agent2 zabbix-agent2 Zabbix Agent 2
sin puertos sin puertos sin puertos
en escucha en escucha en escucha
| | |
| los AGENTES se conectan al server |
| (saliente, sin abrir nada aqui) |
+------------------+--------------------+
|
v
[ZABBIX SERVER - Docker] IP_HOST_DOCKER
puerto 10051 (unico puerto que hay que abrir)
|
v
[ZABBIX DB - MySQL, Docker]
|
v
[ZABBIX WEB - Nginx, Docker]
puerto 8080 -> frontend
zabbix_get) consulte un valor bajo demanda en cualquier momento, sin esperar al siguiente ciclo del agente.| Checks ACTIVOS (esta guia) | Checks PASIVOS (alternativa) | |
|---|---|---|
| Quien inicia la conexion | El agente, hacia el server | El server, hacia el agente |
| Puerto a abrir | Solo 10051 en el server | 10050 en cada agente |
| Superficie de firewall en los endpoints | Ninguna | Un puerto por endpoint |
Consulta bajo demanda (zabbix_get) | No, hay que esperar al ciclo del agente | Si, inmediata |
| Plantilla a usar en el host | ... by Zabbix agent active | ... by Zabbix agent (sin "active") |
4. Requisitos
- Un host Linux con Docker Engine y el plugin Docker Compose (
docker compose, sin guion) ya instalados. Este mismo host tambien va a llevar un agente Zabbix nativo, como un endpoint mas. - El Ubuntu Server a monitorizar, con acceso
sudo. - El equipo Windows 11 a monitorizar, con acceso administrador (PowerShell como administrador).
- Conectividad de red: con el modelo de checks activos que sigue esta guia, basta con que Ubuntu Server y Windows 11 puedan alcanzar el puerto 10051 del host Docker (conexion saliente desde cada agente); el propio host Docker habla consigo mismo por
127.0.0.1, sin salir a la red.
5. Levantar el stack de Zabbix con Docker
Seguimos la misma organizacion de siempre: cada stack vive en su propia carpeta dentro de /docker, y las contraseñas van en un .env aparte, nunca escritas dentro del docker-compose.yml.
sudo mkdir -p /docker/zabbix && cd /docker/zabbix sudo nano .env
Contenido del .env. Al ser una maquina virtual de pruebas para la clase, dejamos estas contraseñas tal cual (en un entorno real, cambialas):
MYSQL_DATABASE=zabbix MYSQL_USER=zabbix MYSQL_PASSWORD=zabbix_pwd MYSQL_ROOT_PASSWORD=zabbix_root_pwd
sudo chmod 600 .env para que solo root pueda leer el archivo de contraseñas.Ahora el archivo del stack, en la misma carpeta:
sudo nano docker-compose.yml
services:
zabbix-db:
image: mysql:8.0
container_name: zabbix-mysql
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_bin
- --log-bin-trust-function-creators=1
environment:
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- zabbix-db-data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p\"$$MYSQL_ROOT_PASSWORD\" --silent"]
interval: 5s
timeout: 5s
retries: 20
start_period: 40s
restart: unless-stopped
zabbix-server:
image: zabbix/zabbix-server-mysql:alpine-7.0-latest
container_name: zabbix-server
environment:
DB_SERVER_HOST: zabbix-db
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ports:
- "10051:10051"
depends_on:
zabbix-db:
condition: service_healthy
restart: unless-stopped
zabbix-web:
image: zabbix/zabbix-web-nginx-mysql:alpine-7.0-latest
container_name: zabbix-web
environment:
DB_SERVER_HOST: zabbix-db
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
ZBX_SERVER_HOST: zabbix-server
PHP_TZ: Europe/Madrid
ports:
- "8080:8080"
depends_on:
zabbix-db:
condition: service_healthy
zabbix-server:
condition: service_started
restart: unless-stopped
volumes:
zabbix-db-data:
Levanta el stack desde /docker/zabbix:
cd /docker/zabbix docker compose up -d watch docker compose ps
.env automaticamente si esta en la misma carpeta que el docker-compose.yml — no hace falta indicarlo aparte. Las tres variables MYSQL_* se rellenan igual en zabbix-db, zabbix-server y zabbix-web porque los tres leen del mismo .env; si algun contenedor no arranca bien, lo primero es comprobar que el .env esta realmente en /docker/zabbix y no en otra carpeta.healthcheck de zabbix-db evita que zabbix-server conecte antes de que MySQL este listo, pero hay una segunda trampa, mas importante, en el primer arranque: MySQL 8 trae el binary logging activado por defecto, y el esquema de Zabbix necesita crear varias funciones y triggers que requieren privilegio SUPER para saltarse esa restriccion. Sin el flag --log-bin-trust-function-creators=1 del comando de arriba, la importacion del esquema falla a mitad (creando dbversion pero no users, por ejemplo) con un error del tipo ERROR 1419: You do not have the SUPER privilege and binary logging is enabled que queda oculto porque el contenedor se reinicia solo tras el fallo. En el segundo intento, zabbix-server ve que la base "ya existe" y no vuelve a intentar importarla, quedando en bucle con el error de "users" table is empty para siempre. Con el flag incluido desde el primer arranque, esto no deberia pasar.6. Primer acceso al frontend y verificacion del stack
Gracias al healthcheck del paso anterior, zabbix-server no arranca hasta que zabbix-mysql esta realmente listo. Comprueba el orden con:
docker compose ps
zabbix-mysql debe mostrar (healthy) en la columna STATUS antes de que zabbix-server pase a Up. Ahora si, sigue el log del servidor:
docker logs -f zabbix-server
Busca una linea similar a Starting Zabbix Server. Zabbix 7.0.x (revision ...) seguida de server #0 started [main process], sin ningun error de "users" table is empty por el camino. Sal con Ctrl+C y entra en el frontend:
server #N started [...] (pollers, discoverers, history pollers...) y despues, normalmente, un puñado de avisos sobre el host interno "Zabbix server" (el que usa Zabbix para monitorizarse a si mismo): cosas como item "...snmp trapper..." became not supported o Zabbix agent item "system.swap.size[,free]" ... failed: first network error. Son normales por ahora: los procesos opcionales (SNMP trapper, VMware collector, report writer...) no arrancan por defecto, y ese host interno todavia no tiene un agente detras — eso lo resolvemos en los pasos 7 y 8.http://IP_HOST_DOCKER:8080
docker-compose.yml. Deberia ir directo a la pantalla de login.Credenciales por defecto en una instalacion nueva:
Usuario: Admin Contraseña: zabbix
Admin nada mas entrar (icono de usuario, arriba a la derecha → Profile), sobre todo si el puerto 8080 va a quedar accesible mas alla de tu red local de pruebas.zabbix-server muestra un error de base de datos incompleta, no hace falta diagnosticar nada a fondo en directo. Un reinicio limpio soluciona un primer arranque fallido en segundos: docker compose down -v seguido de docker compose up -d vuelve a crear la base de datos desde cero.7. Instalar el agente en Ubuntu Server
En el Ubuntu Server a monitorizar (no en el host Docker), añade el repositorio oficial de Zabbix. Ejemplo para Ubuntu 26.04 (Resolute) con Zabbix 7.0 — comprueba el nombre exacto del .deb en zabbix.com/download si tu version difiere:
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0+ubuntu26.04_all.deb sudo dpkg -i zabbix-release_latest_7.0+ubuntu26.04_all.deb sudo apt update sudo apt install zabbix-agent2 -y
Edita la configuracion del agente:
sudo nano /etc/zabbix/zabbix_agent2.conf
Busca y ajusta estas tres lineas (quita el # si estan comentadas):
Server=IP_HOST_DOCKER ServerActive=IP_HOST_DOCKER Hostname=HOSTNAME_UBUNTU
Reinicia el servicio para aplicar el cambio:
sudo systemctl restart zabbix-agent2 sudo systemctl enable zabbix-agent2 sudo systemctl status zabbix-agent2
IP_HOST_DOCKER:10051, no al reves. Lo unico que debe estar abierto es el puerto 10051 en el host Docker (ya expuesto en el docker-compose.yml del paso 5). Si en tu caso prefieres el modelo pasivo (ver seccion 3), entonces si tocaria sudo ufw allow 10050/tcp aqui.Confirma que el proceso esta activo y que consigue conectar de salida al server:
systemctl is-active zabbix-agent2 nc -zv IP_HOST_DOCKER 10051 sudo tail -f /var/log/zabbix/zabbix_agent2.log
no active checks on server o empty list of active checks en este punto: el agente ya intenta hablar con el server, pero el host todavia no existe en el frontend (eso se hace en el siguiente paso). No es un error, es el orden logico de la configuracion.Hostname distingue mayusculas de minusculas y debe coincidir letra por letra con el Host name que le pongas despues en el frontend (paso 8). Es la causa numero uno de que un host "no se vincule" aunque el agente este activo y conectado.8. Añadir el host de Ubuntu Server en el frontend
En el frontend: Data collection → Hosts → Create host.
- Host name:
HOSTNAME_UBUNTU(identico alHostnamedel paso 7) - Host groups: crea o selecciona un grupo, por ejemplo
Linux servers - Interfaces: con checks activos no es obligatorio añadir una interfaz Agent; puedes dejarlo sin interfaces
- Templates:
Linux by Zabbix agent active
Linux by Zabbix agent (sin "active"), sus items apareceran como "Not supported" porque esa plantilla espera que el server pueda conectar al agente por el puerto 10050, cosa que en este montaje no ocurre.Monitoring → Latest data deberian empezar a aparecer valores en el siguiente ciclo de checks activos (por defecto cada 1-2 minutos). Con checks activos el icono ZBX del listado de Hosts no aplica del mismo modo que en pasivo: la señal real de que funciona es que lleguen datos, no ese icono.9. Instalar el agente en el propio host Docker
Antes de pasar a los otros dos equipos, aprovechamos para monitorizar tambien la maquina que aloja el stack de Zabbix. Desde el punto de vista del agente es un Ubuntu como cualquier otro; la unica diferencia es que el server esta en la misma maquina, no al otro lado de la red.
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest_7.0+ubuntu26.04_all.deb sudo dpkg -i zabbix-release_latest_7.0+ubuntu26.04_all.deb sudo apt update sudo apt install zabbix-agent2 -y
Edita la configuracion del agente:
sudo nano /etc/zabbix/zabbix_agent2.conf
Busca y ajusta estas tres lineas. Ojo: aqui Server y ServerActive apuntan a 127.0.0.1, no a la IP de red — agente y server viven en la misma maquina, no hace falta salir por la tarjeta de red para hablar con uno mismo:
Server=127.0.0.1 ServerActive=127.0.0.1 Hostname=HOSTNAME_DOCKER
Reinicia el servicio y comprueba que arranco:
sudo systemctl restart zabbix-agent2 sudo systemctl enable zabbix-agent2 systemctl is-active zabbix-agent2
Y que consigue conectar de salida al server (que en este caso tambien es 127.0.0.1, en el puerto donde docker-compose.yml publica zabbix-server):
nc -zv 127.0.0.1 10051 sudo tail -f /var/log/zabbix/zabbix_agent2.log
Hostname distingue mayusculas de minusculas y debe coincidir letra por letra con el Host name que le pongas despues en el frontend (paso 10). Es la causa numero uno de que un host "no se vincule" aunque el agente este activo y conectado.10. Añadir el host del servidor Docker en el frontend
Zabbix trae de fabrica un host de demostracion llamado exactamente Zabbix server, pensado justo para este caso: monitorizar la propia instalacion con un agente local. En vez de crear un host nuevo, lo aprovechamos — pero trae dos cosas mal configuradas de fabrica para un montaje con Docker, y hay que corregirlas.
- Ve a
Data collection → Hosts → Zabbix server - Pestaña Host: en Interfaces hay una interfaz Agent apuntando a
127.0.0.1:10050. Quitala (Remove). Con checks activos no hace falta, y ademas es incorrecta: ese127.0.0.1es el del contenedorzabbix-server, no el de la maquina fisica — son namespaces de red distintos, nunca van a poder hablarse por ahi. - Pestaña Templates: quita (Unlink) la plantilla
Linux by Zabbix agent(pasiva) y añadeLinux by Zabbix agent activeen su lugar. DejaZabbix server healthtal cual, esa usa checks internos y no depende de ningun agente. - Host name: debe quedar identico al
Hostnameque pusiste en el agente (paso 9). Si prefieres otro nombre, cambia uno de los dos lados para que coincidan.
Host name: HOSTNAME_DOCKER Templates: Zabbix server health + Linux by Zabbix agent active Interfaces: ninguna (no hace falta con checks activos)
Linux: Zabbix agent is not available del dashboard y empezar a llegar metricas de este host en Monitoring → Latest data.Host name: HOSTNAME_DOCKER, plantilla Linux by Zabbix agent active, sin interfaces. Funciona exactamente igual; es solo cuestion de si prefieres reciclar el host de fabrica o partir de uno limpio.11. Instalar el agente en Windows 11
Descarga el instalador MSI de Zabbix Agent 2, version 7.0.x (misma rama LTS que el server), desde zabbix.com/download_agents. Puedes descargarlo directamente por PowerShell (revisa en la pagina de descargas cual es el numero de patch actual antes de lanzarlo):
$msiUrl = "https://cdn.zabbix.com/zabbix/binaries/stable/7.0/7.0.19/zabbix_agent2-7.0.19-windows-amd64-openssl.msi" Invoke-WebRequest -Uri $msiUrl -OutFile "C:\Users\$env:USERNAME\Downloads\zabbix_agent2.msi"
Instala en modo silencioso desde PowerShell como administrador, pasando ya la configuracion:
msiexec /i "C:\Users\$env:USERNAME\Downloads\zabbix_agent2.msi" ` SERVER=IP_HOST_DOCKER ` SERVERACTIVE=IP_HOST_DOCKER ` HOSTNAME=HOSTNAME_WINDOWS ` ENABLEPATH=1 ` SKIP=fw ` /qn /norestart /l*v C:\Users\$env:USERNAME\Downloads\zabbix_install.log
SKIP=fw a proposito: como este equipo solo hace checks activos (sale hacia el server, nadie entra), no necesita ninguna regla de entrada en el puerto 10050. Si en tu caso trabajas con el modelo pasivo (seccion 3), quita ese parametro para que el instalador cree la regla de firewall automaticamente.Comprueba que el servicio se registro y esta en marcha:
Get-Service -Name "Zabbix Agent 2"
Comprueba que llega al puerto del server (checks activos):
Test-NetConnection -ComputerName IP_HOST_DOCKER -Port 10051
Y sigue el log del agente:
Get-Content "C:\Program Files\Zabbix Agent 2\zabbix_agent2.log" -Tail 50 -Wait
TcpTestSucceeded : True en el paso anterior confirma que la red entre el Windows y el host Docker esta bien; el resto (que aparezca como monitorizado) depende de dar de alta el host en el frontend, en el siguiente paso.12. Añadir el host de Windows 11 en el frontend
Igual que con Ubuntu Server: Data collection → Hosts → Create host.
- Host name:
HOSTNAME_WINDOWS(identico alHOSTNAMEdel paso 11) - Host groups: crea o selecciona un grupo, por ejemplo
Windows servers - Interfaces: igual que en Linux, no hace falta interfaz Agent para checks activos
- Templates:
Windows by Zabbix agent active
Monitoring → Latest data deberian empezar a aparecer valores en el siguiente ciclo de checks activos.13. Verificar que llegan datos
Ve a Monitoring → Latest data, filtra por cada uno de los tres hosts (host Docker, Ubuntu Server y Windows 11) y comprueba que aparecen metricas con valores y marca de tiempo reciente: uso de CPU, memoria disponible, espacio en disco, etc. Esto lo trae ya la plantilla que asignaste en cada alta, sin necesidad de crear items manualmente.
Buen cierre para el video: abre una grafica (icono de grafica junto a cualquier item, por ejemplo CPU utilization) para mostrar visualmente que los datos ya fluyen en el tiempo.
14. Tabla de puertos y componentes
| Puerto | Componente | Sentido de la conexion | Para que sirve |
|---|---|---|---|
| 8080/tcp | zabbix-web (Docker) | Navegador → contenedor | Frontend web de Zabbix |
| 10051/tcp | zabbix-server (Docker) | Agentes → server | Unico puerto necesario en este montaje. Checks activos: cada agente (incluido el del propio host Docker) envia datos por iniciativa propia |
| 10050/tcp | Agente Docker / Ubuntu / Windows | Server → agente | No se usa en esta guia. Solo aplica si cambias al modelo pasivo (ver seccion 3) |
| 3306/tcp | zabbix-db (Docker, interno) | zabbix-server / zabbix-web → zabbix-db | Conexion a MySQL; no necesita exponerse al host |
15. Errores comunes y como resolverlos
| Problema | Causa probable | Solucion |
|---|---|---|
El contenedor zabbix-server se reinicia en bucle |
El .env no esta en /docker/zabbix (Compose no lo carga desde otra carpeta) |
docker logs zabbix-server; confirmar con docker compose config que las variables MYSQL_* se resolvieron y no aparecen vacias |
El log de zabbix-server repite cannot use database "zabbix": its "users" table is empty |
MySQL 8 fallo al crear las funciones/triggers del esquema por tener el binary logging activo sin log_bin_trust_function_creators; la importacion quedo a medias y en el reintento automatico ya no se repite |
docker compose down -v para borrar la base a medias, confirmar que el command: de zabbix-db incluye --log-bin-trust-function-creators=1 (seccion 5) y docker compose up -d de nuevo |
| El frontend no carga o da error de conexion a BD | Variables de entorno no llegaron al contenedor, o zabbix-db no esta healthy todavia |
docker compose ps, docker logs zabbix-web, y docker compose up -d --force-recreate si hiciste cambios en el compose |
El host "Zabbix server" muestra Linux: Zabbix agent is not available |
La interfaz Agent de ese host de demostracion apunta a 127.0.0.1:10050, que dentro del contenedor zabbix-server no es la misma maquina que el host fisico |
Quitar esa interfaz y cambiar a la plantilla Linux by Zabbix agent active (ver seccion 10) |
| Los items de la plantilla aparecen como "Not supported" | Se asigno la plantilla pasiva (... by Zabbix agent) a un host que solo hace checks activos |
Cambiar a la plantilla ... by Zabbix agent active |
| No llegan datos en Latest data pasados varios minutos | El agente no consigue conectar de salida al puerto 10051 del host Docker | nc -zv IP_HOST_DOCKER 10051 (o 127.0.0.1 si es el propio host Docker) desde el propio agente; revisar que el puerto 10051 este publicado en el docker-compose.yml |
| El agente esta activo pero el host nunca se vincula | Hostname del agente no coincide exactamente con el Host name del frontend |
Comparar ambos valores caracter a caracter, incluyendo mayusculas/minusculas |
Quiero consultar un valor puntual con zabbix_get y no responde |
Es el comportamiento esperado: este montaje usa solo checks activos, no hay nada escuchando en el puerto 10050 del agente | Si se necesita esa consulta puntual, cambiar ese host concreto al modelo pasivo (seccion 3) y abrir el puerto 10050 en ese agente |
16. Notas de ampliacion
El montaje de esta guia cubre lo minimo necesario para tener tres endpoints reales monitorizados desde un server en Docker. Para un entorno mas completo se puede ampliar con:
- Cifrado con PSK (TLS) entre agente y server, en lugar de dejar la comunicacion en texto plano — especialmente recomendable si los agentes viven fuera de una red de confianza.
- Zabbix Proxy si en el futuro se añaden agentes en otra ubicacion o red separada, para no exponer el server directamente.
- Alertas por Telegram o email (
Administration → Media typesyAlerta → Actions), para que un umbral de CPU o disco lleno notifique de forma inmediata. - Auto-discovery de red para que Zabbix detecte solo nuevos hosts en un rango de IPs, en vez de darlos de alta uno a uno.
- Triggers y templates propios cuando las plantillas nativas de Linux/Windows no cubran una metrica especifica del entorno.