> ## Content Index
> Fetch the complete content index at: https://blog.craftbytes.it/llms.txt
> Use this file to discover other available public pages before exploring further.

# Monitorare Docker con Zabbix: container, LLD e metriche che contano
- URL: https://blog.craftbytes.it/monitorare-docker-zabbix-container/
- Published: 2026-07-19T20:44:14.000Z
- Updated: 2026-07-19T20:44:14.000Z
- Description: Docker e Zabbix sembrano mondi lontani: uno è dinamico e effimero, l'altro è strutturato e persistente. Eppure il Low-Level Discovery rende questa coppia sorprendentemente efficace. Ecco come ho configurato il monitoraggio dei container in produzione.
- Author: Emanuele
- Tags: zabbix, docker, monitoring, sysadmin, infra

## § Il problema con i container e il monitoraggio tradizionale

Il monitoraggio classico presuppone che le cose abbiano un nome stabile. Hai un host, hai dei servizi, li configuri una volta e dimentichi. Con Docker questo modello si rompe quasi subito.

I container nascono e muoiono. I nomi cambiano tra un deploy e l'altro se non li fissi esplicitamente. Con orchestratori come Swarm o anche semplici compose con scaling, puoi ritrovarti con `app_web_1`, `app_web_2`, `app_web_3` in un pomeriggio e zero container la mattina dopo.

La prima volta che ho provato a monitorare un ambiente Docker con Zabbix "alla vecchia maniera" — item statici, trigger hardcoded per nome container — ho capito dopo due settimane che stavo monitorando ghost. Container che non esistevano più, alert su servizi rinominati, nessuna visibilità sui nuovi container deployati.

La soluzione è il Low-Level Discovery. Esattamente come per i filesystem o le interfacce di rete, Zabbix può scoprire automaticamente i container in esecuzione e creare item, trigger e grafici per ciascuno.

## § Architettura: agent sull'host, non nel container

Prima decisione: dove gira lo Zabbix Agent? Due approcci comuni:

1. **Agent sull'host** — un singolo agent sul nodo Docker, accede al socket `/var/run/docker.sock` e vede tutti i container. Meno overhead, meno complessità.
2. **Agent come sidecar** — un container Zabbix Agent per ogni stack Docker, con accesso al socket montato come volume. Più isolato, ma moltiplica gli agent da gestire.

In produzione uso l'agent sull'host. È più semplice, funziona con il template ufficiale senza modifiche, e non aggiunge un container al compose solo per monitorare gli altri.

L'unica cosa da verificare: l'utente con cui gira l'agent deve poter leggere il socket Docker.

```
# Aggiungi l'utente zabbix al gruppo docker
usermod -aG docker zabbix

# Verifica
id zabbix
# uid=109(zabbix) gid=109(zabbix) groups=109(zabbix),998(docker)
```

Se usi SELinux o AppArmor, configura le policy di conseguenza. Non è questo l'articolo per approfondire SELinux, ma non ignorarlo in produzione.

## § Il template ufficiale: Docker by Zabbix Agent 2

Dal 5.4 in poi Zabbix distribuisce un template Docker ufficiale pensato per **Zabbix Agent 2**, che ha il plugin Docker nativo. Non serve configurare UserParameter o script esterni.

Il template si chiama *Docker by Zabbix agent 2* ed è disponibile su [zabbix.com/integrations/docker](https://www.zabbix.com/integrations/docker?ref=blog.craftbytes.it). Se usi Zabbix 6.x o 7.x, è già incluso nei template di default.

Il prerequisito è usare Agent 2 (`zabbix-agent2`), non il classico `zabbix-agent`. Su Debian/Ubuntu:

```
apt install zabbix-agent2
systemctl enable --now zabbix-agent2
```

Configura il plugin Docker in `/etc/zabbix/zabbix_agent2.d/plugins.d/docker.conf`:

```
Plugins.Docker.Endpoint=unix:///var/run/docker.sock
```

Riavvia l'agent e verifica che il plugin risponda:

```
zabbix_agent2 -t docker.info
```

Se vedi JSON con le info del daemon Docker, sei a posto.

## § Come funziona il LLD per i container

Il template usa una regola di discovery su `docker.containers.discovery`. Zabbix Agent 2 interroga il socket Docker, riceve la lista dei container (running e stopped, configurabile), e restituisce un JSON con le macro per ogni container:

```
[
  {"{#NAME}": "nginx", "{#ID}": "a3f8...", "{#STATUS}": "running", "{#IMAGE}": "nginx:1.25"},
  {"{#NAME}": "postgres", "{#ID}": "b9c1...", "{#STATUS}": "running", "{#IMAGE}": "postgres:16"},
  ...
]
```

Da queste macro vengono generati automaticamente item per ogni container:

- Stato container (`docker.container.info["{#NAME}",State.Status]`)
- CPU usage
- Memoria utilizzata e limite
- Network I/O (rx/tx bytes)
- Block I/O
- Numero di processi nel container
- Numero di restart

Il filtro di default include solo i container in stato *running*. Se vuoi monitorare anche i container fermi (per trigger su "container non parte"), rimuovi il filtro o aggiungine uno personalizzato.

## § Trigger che uso davvero

Il template include trigger di default, ma in produzione li ho affinati nel tempo. Quelli che hanno fatto la differenza:

### Container non in esecuzione

```
last(/host/docker.container.info["{#NAME}",State.Status])<>"running"
```

Trigger WARNING se il container non è running. Combinato con una dipendenza dall'host, evita falsi positivi durante i riavvii pianificati.

### Restart loop

```
change(/host/docker.container.info["{#NAME}",RestartCount])>0
and
last(/host/docker.container.info["{#NAME}",RestartCount])>3
```

Un container che riavvia spesso è un container che sta soffrendo. Questo trigger scatta quando rileva più di 3 restart totali *e* il contatore è aumentato nell'ultima rilevazione. Il `change()` evita alert persistenti su un container già in recovery stabile.

### Memoria sopra soglia

```
last(/host/docker.container.stats["{#NAME}",memory_usage])
/ last(/host/docker.container.stats["{#NAME}",memory_limit]) * 100 > 85
```

Utile se hai impostato `mem_limit` nel compose. Se non hai un limite, `memory_limit` ritorna la RAM totale del nodo — in quel caso regola la soglia di conseguenza o skippa il trigger per quei container.

## § Configurare i container per essere monitorabili meglio

Un dettaglio che fa differenza: dai sempre un nome esplicito ai container in Docker Compose.

```
services:
  web:
    image: nginx:1.25
    container_name: myapp-nginx   # nome stabile
  app:
    image: myapp:latest
    container_name: myapp-app     # nome stabile
  db:
    image: postgres:16
    container_name: myapp-postgres
```

Senza `container_name`, Docker usa `projectname_service_N`. Con scaling questo diventa `myapp_web_1`, `myapp_web_2` — ogni nuova istanza crea nuovi item in Zabbix, e le vecchie rimangono come ghost fino al prossimo cleanup. Con nomi fissi, il LLD è deterministico e gli item rimangono stabili.

## § Labels Docker come macro Zabbix

Un trick meno conosciuto: puoi aggiungere label ai container e usarle come filtri nel LLD o come macro nel template.

```
services:
  web:
    image: nginx:1.25
    labels:
      - "monitoring.tier=frontend"
      - "monitoring.alert=true"
      - "monitoring.team=infra"
```

Il plugin Docker le espone come `{#LABEL.*}` nella discovery. Puoi usarle come filtri per escludere container di test, o per raggruppare gli alert per team in Zabbix.

## § Metriche che il template standard non copre

Il template ufficiale copre bene CPU, memoria e network. Mancano alcune cose che ho aggiunto con UserParameter specifici:

### Health check status

Se i tuoi container hanno un `HEALTHCHECK` configurato nell'immagine, Docker espone lo stato in `State.Health.Status`. Puoi monitorarlo così:

```
UserParameter=docker.container.health[*],docker inspect --format='{{.State.Health.Status}}' $1 2>/dev/null || echo "none"
```

Poi un item con chiave `docker.container.health[nginx]` e trigger su valore diverso da `healthy`.

### Numero di container per stato

```
UserParameter=docker.containers.running,docker ps -q --filter status=running | wc -l
UserParameter=docker.containers.stopped,docker ps -q --filter status=exited | wc -l
```

Item aggregati utili per grafici di capacity planning — quanti container attivi sul nodo nel tempo.

## § Pitfalls che ho trovato

**Discovery interval troppo basso.** Con interval a 1 minuto su ambienti con molti deploy al giorno, Zabbix crea e distrugge item in continuazione. Il graceful period (quanto aspetta prima di rimuovere item di container non più presenti) di default è 30 giorni — troppo lungo. L'ho abbassato a 7 giorni per ambienti dinamici.

**Il plugin Docker e le permission sul socket.** Su alcuni sistemi il socket ha permessi 660 con gruppo `docker`, su altri 666\. Dopo ogni update del pacchetto Docker verifico che l'utente `zabbix` sia ancora nel gruppo — gli update a volte ricreano il gruppo con GID diverso.

**Container con nomi Unicode o caratteri speciali.** Ho visto container con emoji nel nome (sì, davvero) che rompevano il parser del template. Soluzione: filtro LLD con regex `^[a-zA-Z0-9_-]+$` per escluderli.

**Zabbix Agent 2 vs Agent classico.** Il plugin Docker funziona *solo* con Agent 2\. Se hai ancora Agent classico su qualche nodo, puoi usare UserParameter con `docker inspect` come fallback, ma perdi la consistenza del template.

## § Vale la pena rispetto ad alternative?

La domanda giusta da farsi è: se hai già Zabbix per il monitoraggio dell'infrastruttura host, aggiungere il monitoraggio Docker ha senso perché ti dà correlazione diretta tra metriche host e metriche container nello stesso sistema. Un picco di CPU sull'host mentre tre container consumano l'80% della loro quota è una storia coerente in un'unica dashboard.

Se parti da zero o hai un ambiente cloud-native con Kubernetes, esistono soluzioni più native (Prometheus+Grafana, Datadog, ecc.). Ma se Zabbix è già il tuo strumento di riferimento per ER network, SNMP, agenti fisici — estenderlo ai container ha un costo marginale basso e ti evita di gestire un secondo stack di monitoraggio.

Come al solito con Zabbix: funziona, scala, non ti fa dormire tranquillo. Ma almeno adesso ti sveglia per le cose giuste.