Hai mai passato un pomeriggio a configurare PHP, MySQL e un server web su un nuovo PC, solo per scoprire che in produzione l'ambiente è diverso? Noi sì, e l'abbiamo odiato. Docker risolve esattamente questo: ogni sviluppatore, ogni server, ogni cliente ha lo stesso identico ambiente. Niente più "sulla mia macchina funziona".
Cos'è un container e perché ti cambia la giornata
Un container è un pacchetto leggero e isolato che contiene tutto il necessario per eseguire un'applicazione: codice, runtime, librerie, variabili d'ambiente. A differenza di una macchina virtuale, non emula un intero sistema operativo: condivide il kernel dell'host. Risultato: occupa meno spazio, parte in secondi, consuma meno risorse.
Noi, di Meteora Web, abbiamo iniziato a usare Docker nel 2018 per un progetto cliente con un'applicazione PHP legacy. Prima, ogni sviluppo su Linux, Mac e Windows era un incubo. Dopo Docker, il setup è diventato un comando unico: docker compose up. Taglio del tempo di onboarding del 70%.
Analogia pratica: i container navali
Prima dei container navali, ogni merce veniva caricata a pezzi — inefficiente, lento, soggetto a danni. I container standard hanno permesso di spostare qualsiasi carico in modo uniforme. Docker fa lo stesso con il software: impacchetta applicazione e dipendenze in un formato standard che gira su qualsiasi macchina con Docker installato.
Immagini e container: la differenza che conta
L'immagine è un template immutabile (un file system leggibile) che contiene l'applicazione e le sue dipendenze. Il container è un'istanza eseguibile creata da quell'immagine. Puoi avere più container dalla stessa immagine, ognuno isolato.
# Scarica l'immagine ufficiale di Nginx
docker pull nginx:latest
# Avvia un container da quell'immagine
docker run -d -p 8080:80 --name mio-nginx nginx:latest
# Verifica che sia in esecuzione
docker psIn questo esempio, nginx:latest è l'immagine. Il container creato ha un proprio filesystem, rete e processi, ma condivide il kernel. Apri http://localhost:8080 e vedrai la pagina di default di Nginx.
Il Registry: dove trovare e condividere immagini
I registry sono repository di immagini. Il più noto è Docker Hub, ma esistono alternative come GitHub Container Registry, GitLab Container Registry o registry privati self-hosted. Puoi push le tue immagini e pull quelle pubbliche.
Perché usare un registry? Per non reinventare la ruota. Invece di configurare manualmente PHP, Apache e MySQL ogni volta, prendi un'immagine ufficiale già pronta. Noi lo facciamo per i nostri clienti: un'immagine base con PHP 8.x, estensioni necessarie, composer preinstallato — tutto in un unico Dockerfile.
# Cerca immagini su Docker Hub dalla riga di comando
docker search ubuntu
# Pull di una versione specifica
docker pull php:8.2-fpmAttenzione: non usare il tag latest in produzione. Le immagini cambiano, e rischi aggiornamenti imprevisti. Specifica sempre una versione esatta, come nginx:1.27.0.
I comandi fondamentali per lavorare con Docker
Questi comandi li usiamo ogni giorno in Meteora Web. Imparali e diventeranno automatici.
Gestione dei container
# Elenca container in esecuzione
docker ps
# Elenca tutti i container (anche fermati)
docker ps -a
# Avvia un container in background (-d), mappa porta (-p), nomina (--name)
docker run -d -p 8080:80 --name mio-web nginx:1.27.0
# Ferma un container
docker stop mio-web
# Rimuovi un container (deve essere fermato)
docker rm mio-web
# Rimuovi forzatamente mentre è in esecuzione
docker rm -f mio-webGestione delle immagini
# Elenca immagini locali
docker images
# Rimuovi un'immagine
docker rmi nginx:1.27.0
# Rimuovi immagini non utilizzate (pulisce spazio)
docker image prune -aEsplorare un container in esecuzione
# Apri una shell interattiva dentro il container
docker exec -it mio-web /bin/bash
# Visualizza i log in tempo reale
docker logs -f mio-webEsempio pratico completo: vogliamo testare un'app Node.js su una macchina senza Node installato. Basta un comando:
docker run -it --rm -v "$(pwd):/app" -w /app node:20-alpine node app.jsIl flag --rm elimina il container al termine, -v monta la directory corrente, -w imposta la directory di lavoro. Ambiente pulito, nessuna installazione.
Dal codice all'immagine: il Dockerfile
Quando le immagini ufficiali non bastano, crei la tua. Il Dockerfile è un ricettario che descrive come costruire un'immagine. Noi ne scriviamo uno per ogni progetto cliente: garantisce che l'ambiente di sviluppo, staging e produzione sia identico.
# Usa un'immagine base ufficiale
FROM nginx:alpine
# Copia i file dell'app nella directory del server web
COPY ./sito /usr/share/nginx/html
# Espone la porta 80
EXPOSE 80
# Comando di default (già presente nell'immagine base, ma esplicito)
CMD ["nginx", "-g", "daemon off;"]Ora costruisci l'immagine e la esegui:
docker build -t mio-sito:v1 .
docker run -d -p 8080:80 mio-sito:v1Errori comuni nei Dockerfile:
- Copiare tutto (
COPY . .) senza.dockerignore— includi node_modules, file temporanei, aumentando inutilmente la dimensione. - Usare
latestcome base — meglio fissare versione esatta (es.nginx:1.27-alpine). - Eseguire aggiornamenti di sistema in ogni build — usa immagini già aggiornate.
Build e push: condividere la tua immagine
# Costruisci con un tag comprensivo del registry e del nome utente
docker build -t tuo-utente/mio-sito:v1 .
# Accedi a Docker Hub (o altro registry)
docker login
# Carica l'immagine sul registry
docker push tuo-utente/mio-sito:v1Da questo momento, chiunque (o qualsiasi server) può eseguire docker pull tuo-utente/mio-sito:v1 e avere esattamente la stessa applicazione. Noi lo usiamo per distribuire aggiornamenti ai clienti senza dover configurare manualmente ogni server.
Ottimizzazione: immagini piccole, costi bassi
Un cliente e-commerce aveva immagini Docker da 2,1 GB per un'app Node.js. Analizzando i layer, abbiamo scoperto che includevano tool di sviluppo, cache di npm e file non necessari. Con un multi-stage build e immagini alpine, siamo scesi a 120 MB. Riduzione del 94%. Su 10 server, il risparmio di spazio e banda è stato enorme.
# Multi-stage build: separa compilazione da runtime
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]Sicurezza: non lasciare porte aperte
I container non sono intrinsecamente sicuri. Se esegui il container come root, un attaccante potrebbe escalare privilegi. Noi, di Meteora Web, seguiamo queste regole:
- Usa immagini ufficiali e conosciute (Docker Official Images o immagini verificate).
- Esegui i container con utente non-root (direttiva
USERnel Dockerfile). - Non esporre porte inutili: mappa solo quelle necessarie.
- Aggiorna regolarmente le immagini di base: un container vecchio è una vulnerabilità.
# Creare un utente non-root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuserIn sintesi — cosa fare adesso
- Installa Docker sul tuo sistema operativo: segui la guida ufficiale su docs.docker.com.
- Esegui il tuo primo container:
docker run hello-world— verifica che tutto funzioni. - Metti le mani su Nginx: scarica l'immagine (
docker pull nginx:alpine), avvia un container con porta mappata, modifica la pagina default e ricarica. - Scrivi un Dockerfile per un progetto esistente (anche una pagina HTML statica) e costruisci la tua immagine.
- Esplora Docker Hub per trovare immagini utili per il tuo stack (PHP, Python, PostgreSQL).
Da qui in poi tutto diventa riproducibile, portabile e misurabile. Esattamente come piace a noi.
Sponsored Protocol