Docker è una piattaforma di containerizzazione che isola applicazioni e dipendenze in ambienti portabili, permettendo deploy rapidi e rollback immediati in produzione. Un container racchiude tutto il necessario per eseguire un software, eliminando i conflitti sull’host.
| Concetto | Descrizione | Comando base |
|—|—|—|
| Immagine | Blueprint read-only del software | docker pull nginx |
| Container | Istanza live dell’immagine | docker run -d nginx |
| Volume | Persistenza dati esterna al container | docker volume create miei-dati |
| Compose | Orchestrazione multi-container | docker compose up -d |
Applicazione deployata direttamente sul server host. Aggiornamento della dipendenza va in conflitto. Produzione down per 2 ore. Il container avrebbe isolato il problema in 10 secondi. Ho vissuto questo scenario più volte prima di adottare Docker sistematicamente. Quando ho consolidato un ambiente con 300+ VM, il problema ricorrente era il conflitto di librerie tra servizi legacy e applicazioni moderne sulla stessa macchina. La separazione fisica tramite VM era costosa in termini di risorse. La separazione logica tramite container ha ridotto il footprint del 60% e azzerato i conflitti di runtime. Il 73% delle organizzazioni usa container in produzione oggi (CNCF Annual Survey 2025). I container riducono i tempi di deploy del 70% rispetto ai metodi tradizionali (Sysdig 2025). Questa è una guida operativa per sysadmin, non un manifesto teorico.
Docker in 3 minuti — cosa risolve e quando usarlo
Docker risolve il problema dell’isolamento software senza l’overhead di una VM completa. Un container condivide il kernel dell’host ma mantiene processi, filesystem e rete isolati. Quando aggiorni una libreria dentro un container, l’host e gli altri container non sanno che è successo.
Usa Docker quando:
- Devi runnare servizi con dipendenze in conflitto (Python 3.11 vs Python 2.7).
- Hai bisogno di deploy rapidi e rollback in secondi.
- Vuoi standardizzare l’ambiente di sviluppo e produzione.
Non usare Docker per:
- Applicazioni monolitiche strettamente legate al kernel host (alcuni driver hardware specifici).
- Database ad alte prestazioni che necessitano accesso diretto al I/O fisico (se non hai storage ottimizzato per container).
Installazione su Ubuntu/Debian
L’installazione su Ubuntu 24.04 o Debian 12 richiede un singolo comando ufficiale. Evita i repository di default della distro, spesso contengono versioni vecchie.
curl -fsSL https://get.docker.com | sh
Questo script rileva la distro, aggiunge il repository Docker GPG e installa l’engine. Al termine, aggiungi il tuo utente al gruppo docker per evitare sudo su ogni comando.
sudo usermod -aG docker $USER
Logout e login di nuovo per applicare i permessi. Verifica l’installazione:
docker --version
docker run hello-world
Se il container hello-world parte, l’engine è operativo.
Immagini e container — la differenza che conta
L’errore più comune per un sysadmin che inizia è confondere immagini e container. L’immagine è il template. Il container è il processo live. Pensa all’immagine come alla classe in programmazione e al container come all’oggetto istanziato.
Un’immagine si compone di layer read-only. Quando avvii un container, Docker aggiunge un layer write-only sopra i layer dell’immagine. Se stoppi e rimuovi il container, il layer write-only svanisce. I dati modificati vengono persi.
# Scarica l'immagine Nginx latest
docker pull nginx
# Avvia un container dall'immagine
docker run -d -p 80:80 nginx
Il flag -d detach il container in background. Il flag -p 80:80 mappa la porta 80 dell’host sulla porta 80 del container. Senza questa mappatura, Nginx risponde solo dentro la rete isolata del container.
I comandi Docker che usi ogni giorno
La giornata di un sysadmin con Docker si riduce a una manciata di comandi ripetuti. Impara questi a memoria.
# Lista container attivi
docker ps
# Lista tutti i container, inclusi quelli stoppati
docker ps -a
# Leggi i log di un container
docker logs container_id
# Entra dentro un container in esecuzione
docker exec -it container_id bash
# Stoppa un container
docker stop container_id
# Rimuovi un container stoppato
docker rm container_id
Il comando docker exec -it container_id bash è il tuo SSH dentro il container. Usalo per debug rapido. Se l’immagine non ha bash installata (come Alpine), usa sh al posto di bash.
Il comando docker logs container_id mostra lo stdout del processo principale. Aggiungi -f per seguire i log in real time, simile a tail -f.
Dockerfile — costruire la tua prima immagine
Scaricare immagini preconfezionate funziona per test. In produzione buildi immagini custom con un Dockerfile. Un Dockerfile è una sequenza di istruzioni per assemblare un’immagine layer per layer.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/index.html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Ogni istruzione crea un layer. FROM definisce la base. RUN esegue comandi nel layer. COPY inserisce file dall’host. EXPOSE documenta la porta. CMD definisce il processo principale del container.
Builda l’immagine:
docker build -t mio-nginx:1.0 .
Il flag -t assegna un tag nome:versione. Il . indica che il Dockerfile si trova nella directory corrente. Docker esegue le istruzioni in ordine e cache i layer. Se modifichi solo index.html, Docker re-esegue solo il layer COPY e quelli successivi.
Docker Compose — multi-container in un file
Quando un’applicazione richiede più servizi (web server, database, cache), Docker Compose orchestra tutto con un file YAML. Compose elimina la necessità di lanciare e collegare container manualmente con lunghi comandi.
version: '3.8'
services:
web:
image: mio-nginx:1.0
ports:
- "80:80"
db:
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=segreto
volumes:
db-data:
Avvia l’intero stack con un comando:
docker compose up -d
Compose crea una rete isolata per lo stack. I container si risolvono per nome servizio. Il container web contatta il database usando l’hostname db, non un IP hardcoded.
Volumi e persistenza dei dati
I container sono ephemeral per design. Se un container crasha o viene ricreato, i dati nel filesystem interno svaniscono. Per un database o un’applicazione stateful, questo è un problema critico.
Docker risolve questo con i volumi. Un volume è una directory sull’host montata dentro il container.
# Crea un volume nominato
docker volume create miei-dati
# Monta il volume in un container
docker run -d -v miei-dati:/var/lib/postgresql/data postgres:16
Il flag -v mappa il volume miei-dati sulla directory interna del container PostgreSQL. I dati scritti dentro /var/lib/postgresql/data persistono sull’host anche se il container viene distrutto.
Per configurazioni statiche, monta un file dell’host:
docker run -d -v /etc/localtime:/etc/localtime:ro nginx
Il flag :ro imposta il mount come read-only. Il container legge la timezone dell’host ma non può alterarla.
Networking Docker — comunicare tra container
Docker gestisce la rete in modo trasparente. Di default crea una rete bridge per ogni stack Compose. I container nella stessa rete comunicano usando i nomi dei servizi come hostname.
Per esporre un servizio all’esterno, mappa le porte:
docker run -d -p 8080:80 nginx
La porta 8080 dell’host route il traffico sulla porta 80 del container.
Se hai bisogno di isolamento totale, crea una rete custom:
docker network create rete-isolata
docker run -d --network rete-isolata --name app1 mio-nginx:1.0
docker run -d --network rete-isolata --name app2 alpine
I container app1 e app2 comunicano tra loro. Nessun container esterno alla rete può raggiungerli.
Aggiornare un container in produzione senza downtime
L’approccio naive per aggiornare un container è stoppare il vecchio e avviare il nuovo. In produzione questo causa downtime. Il metodo corretto per un sysadmin è il blue-green deployment usando un reverse proxy.
- Avvia il container aggiornato su una porta differente.
- Aggiorna la configurazione del reverse proxy (Nginx, HAProxy) per puntare alla nuova porta.
- Stoppa il container vecchio.
# Avvia nuova versione sulla porta 8081
docker run -d -p 8081:80 --name web-v2 mio-nginx:2.0
# Switch traffico reverse proxy su 8081
# ... modifica config proxy ...
# Stoppa e rimuovi vecchio container
docker stop web-v1
docker rm web-v1
Se la nuova versione ha un bug, rollback in 10 secondi. Riattiva web-v1 e sposta il traffico indietro.
Pulisci le vecchie immagini per liberare spazio su disco:
docker system prune -a
Questo comando rimuove container stoppati, immagini inutilizzate e cache dei layer. Attenzione: elimina tutto ciò che non è usato da un container attivo.
Errori comuni e troubleshooting
Container si stoppa subito dopo docker run
Controlla i log. Il processo principale crasha.
docker logs container_id
Se il Dockerfile ha una CMD sbagliata o una dipendenza mancante, i log mostrano l’errore esatto.
Porta già in uso sull’host
Se docker run -d -p 80:80 nginx fallisce, un processo sull’host occupa la porta 80. Cambia la porta dell’host (-p 8080:80) o stoppa il processo conflittuale.
Permission denied sui volumi
Il processo nel container runna come utente root o un utente specifico. Se monta una directory dell’host, l’utente del container deve avere permessi di scrittura su quella directory. Soluzione: aggiusta i permessi sull’host o specifica l’utente nel Dockerfile con USER.
Spazio su disco esaurito
Docker accumula layer e immagini morte. Monitora lo spazio con docker system df. Se i percentuali hit 90%, esegui docker system prune -a.
FAQ — Domande Frequenti
Posso usare Docker per runnare un database in produzione?
Sì, ma con cautela. I database richiedono persistenza garantita e I/O stabile. Usa volumi Docker su storage performante (SSD/NVMe). Evita i bind mount su filesystem network lenti. PostgreSQL e MySQL girano bene in container se configurati con volumi dedicati e limiti di risorse.
Docker sostituisce le VM?
No. Docker condivide il kernel dell’host. Se hai bisogno di kernel diversi, isolamento hardware completo, o runnare OS differenti simultaneamente, le VM restano necessarie. Docker sostituisce le VM solo quando l’isolamento logico basta per il workload.
Come gestisco i log di 50 container senza impazzire?
Docker scrive i log in JSON file sull’host. Per 50 container, la dimensione esplode. Configura un log driver esterno (Syslog, Fluentd, o local with rotation). Limita la dimensione dei log per container con --log-opt max-size=10m --log-opt max-file=3 nel comando run.
Qual è la differenza tra Docker Compose e Kubernetes?
Compose orchestra container su un singolo host. Kubernetes orchestra container su cluster multi-host con auto-scaling e self-healing. Se hai un singolo server, Compose basta. Se hai un ambiente con 300+ VM e necessiti di alta affidabilità, Kubernetes è la scelta corretta.
Docker è gratuito?
L’engine Docker (containerd, runc) è open source. Docker Desktop per Mac/Windows è gratuito per piccole aziende, ma richiede licenza per enterprise. Su Linux server, l’engine è sempre gratuito.
Conclusioni con takeaway operativi
Docker risolve il problema dell’isolamento software con un overhead minimo. Per un sysadmin, il vantaggio principale è la predictability. Se un container gira sul tuo laptop, gira in produzione con lo stesso comportamento.
Tre takeaway operativi:
- Installa Docker con lo script ufficiale, non dai repo distro.
- Usa sempre volumi per i dati stateful. I container sono ephemeral per design.
- Aggiorna in produzione con il blue-green deployment, mai stop and pray.
Il prossimo passo è Docker Compose. Se gestisci più di 3 container manualmente, Compose riduce la complessità a un singolo file YAML. Per approfondimenti, consulta la documentazione ufficiale su docs.docker.com.
Leggi anche
Leggi anche: Nginx come reverse proxy — configurazione completa con esempi
Leggi anche: Kubernetes — da zero al primo pod in produzione
Leggi anche: Lynis Audit Sicurezza Linux: Guida Completa e Pratica (2026)
Aggiornato: Aprile 2026