LIVE · blog.craftbytes.it session / 042 · issue IT · EN · edizione bilingue
docker / 19 lug 2026 / 4 min lettura

Docker in produzione per sysadmin: guida pratica senza fronzoli

Docker non è solo roba da developer. Per un sysadmin Linux è uno degli strumenti più pratici in produzione: meno VM, meno dipendenze, deploy ripetibili. Guida pratica senza teoria inutile.

Docker in produzione per sysadmin: guida pratica senza fronzoli
Photo by Ian Taylor / Unsplash

Se sei un sysadmin e hai resistito a Docker finora, capisco la diffidenza. Docker nasce con un'aura "dev-friendly" che a volte fa sembrare lo strumento adatto solo per chi scrive codice. In realtà è uno degli strumenti più utili che puoi aggiungere al tuo arsenale operativo, specialmente se gestisci server Linux in ambienti PMI o MSP.

Questa guida è scritta per chi conosce Linux, sa usare il terminale, e vuole capire come portare Docker in produzione senza perdere il controllo di quello che gira sui propri server.


Installazione su Linux (senza Docker Desktop)

Docker Desktop non serve su Linux. Serve sul Mac o Windows quando non hai accesso diretto al kernel Linux. Su un server Ubuntu o Debian, installi direttamente il demone:

# Ubuntu 22.04 / 24.04
curl -fsSL https://get.docker.com | sh

# Aggiungi il tuo utente al gruppo docker (eviti sudo ogni volta)
sudo usermod -aG docker $USER
newgrp docker

# Verifica
docker version

Lo script ufficiale di Docker è quello che si usa in produzione. Non usare il pacchetto docker.io dai repo Ubuntu: è vecchio e mancano le ultime feature.


I quattro concetti che devi capire (e solo questi)

Docker ha una terminologia che all'inizio sembra più complicata di quello che è. Ti servono solo quattro concetti:

  • Image: il blueprint del container, read-only. Come un template VM, ma leggero.
  • Container: istanza in esecuzione di un'image. Puoi averne cento dalla stessa image.
  • Volume: dove metti i dati persistenti. Tutto il resto del container è effimero.
  • Network: come i container parlano tra loro (e con l'esterno).

Tutto il resto, registry, layer, overlay filesystem, viene da sé una volta che hai questi chiari.


Docker Compose: lo strumento reale per la produzione

Nessuno gestisce container in produzione con comandi docker run lanciati a mano. Lo strumento che usi ogni giorno si chiama Docker Compose, ed è incluso in Docker moderno (docker compose, senza trattino).

Un file compose.yml descrive tutto ciò che serve per far girare un'applicazione:

services:
  app:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  db:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  postgres_data:

Con questo file, avvii tutto con docker compose up -d e spegni tutto con docker compose down. Semplice da versionare su Git, semplice da replicare su un altro server.


Restart policy: fondamentale, spesso ignorata

Se un container crasha e non hai configurato la restart policy, rimane giù finché non lo riavvii a mano. In produzione questo non è accettabile.

Le opzioni che usi in pratica:

  • restart: unless-stopped riavvia sempre, tranne se l'hai fermato tu esplicitamente con docker stop. Quello che vuoi in produzione.
  • restart: always riavvia sempre, anche dopo un docker stop. Utile se vuoi che riparta al boot automaticamente.
  • restart: on-failure riavvia solo se esce con codice di errore. Per job e cron container.
  • restart: no non riavvia mai. Default. Non usarlo in produzione.

Logging: non riempire il disco

Il problema più comune sui server Docker in produzione è il disco che si riempie di log. Per default Docker accumula i log JSON senza limiti. Soluzione: configurare il log driver globalmente.

Modifica /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Poi ricarica Docker:

sudo systemctl reload docker

I nuovi container useranno questi limiti automaticamente. I container esistenti vanno ricreati per applicare la modifica.

Se hai già uno stack di log centralizzato (Loki, ELK), puoi usare i driver loki o gelf argomento per un articolo dedicato.


Volumi: dove finiscono i tuoi dati

Regola fondamentale: tutto ciò che deve sopravvivere al container va su un volume. I container sono usa e getta, l'image si aggiorna, il container si ricrea, i dati restano sul volume.

Due modi per montare dati:

# Bind mount: mappa una cartella dell'host nel container
volumes:
  - /opt/myapp/config:/app/config

# Named volume: gestito da Docker, preferibile per database
volumes:
  - postgres_data:/var/lib/postgresql/data

Per i database usa sempre named volume. Per file di configurazione che vuoi versionare su Git, il bind mount va bene.

Backup di un named volume:

docker run --rm \
  -v postgres_data:/data \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/postgres_backup_$(date +%Y%m%d).tar.gz -C /data .

Sicurezza base: quello che non puoi ignorare

Docker di default è troppo permissivo per la produzione. Tre regole da applicare sempre:

1. Non girare come root dentro il container

FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

2. Mai --privileged senza una ragione precisa
--privileged dà al container accesso completo all'host. Se un container compromesso gira con questo flag, l'attaccante ha root sul server.

3. Filesystem read-only dove possibile

services:
  app:
    image: myapp:latest
    read_only: true
    tmpfs:
      - /tmp
    volumes:
      - app_data:/app/data

Comandi essenziali per il troubleshooting

# Tutti i container (anche quelli fermi)
docker ps -a

# Log in real-time
docker logs -f nome_container

# Shell dentro il container per debug
docker exec -it nome_container sh

# Uso risorse in real-time (come top, ma per container)
docker stats

# Configurazione completa del container
docker inspect nome_container

# Quanto spazio occupa Docker
docker system df

# Pulizia: immagini, container fermi, volumi orfani
# ATTENZIONE: rimuove anche i volumi non montati
docker system prune -a --volumes

Pattern da non dimenticare in produzione

  • Un servizio per container non mettere nginx + app + database nello stesso container. Rompe scaling e aggiornamento indipendente.
  • Tag specifici, mai latest postgres:latest è una bomba a orologeria. Usa postgres:16.3 e aggiorna con controllo.
  • Segreti fuori dal Compose file usa .env file escluso da Git, o Docker Secrets in ambienti multi-nodo.
  • Health check sempre definito:
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Senza health check, Docker considera il container "up" non appena il processo parte, anche se l'applicazione ci mette 30 secondi ad inizializzarsi o è in crash loop.


Conclusione

Docker in produzione non è complicato se parti dai concetti giusti: Compose per orchestrare, volumi per i dati, restart policy sempre configurata, logging con limiti, sicurezza minima ma presente.

Non serve Kubernetes per la maggior parte dei workload di una PMI o di un MSP. Docker Compose su un server Linux ben configurato copre il 90% dei casi d'uso, con molta meno complessità operativa.

Nel prossimo articolo vedremo come monitorare i container Docker con Zabbix: metriche, alert e LLD per scoprire automaticamente i container che girano sul server.

// condividi x.com ↗ linkedin ↗ hn ↗ email ↗
// newsletter · /dev/subscribe

Dispatches from the rack.

Un'email ogni due settimane: un articolo, uno schema, un comando da ricordare. Niente pubblicità, niente hype.