Scena vista mille volte: hai un notebook che funziona alla perfezione, lo mandi a un collega, e dopo mezz’ora ti scrive «a me dà errore». Versione di Python diversa, una libreria a una minor release di distanza, un pacchetto di sistema che tu avevi installato l’anno scorso e ti sei dimenticato. La frase «sul mio computer funziona» non è una scusa, è la descrizione onesta di un problema: il tuo codice non porta con sé l’ambiente in cui gira. Docker serve esattamente a questo — impacchettare codice e ambiente in un unico oggetto trasportabile — e per usarlo da data scientist non ti servono cento comandi. Te ne bastano tre concetti. Vediamoli, e poi impacchettiamo un modello vero.
Tre parole: immagine, container, volume
Docker sembra intimidatorio perché la sua documentazione è scritta per chi fa infrastruttura. Ma il modello mentale che ti serve sta in tre termini, e c’è un’analogia culinaria che li tiene insieme.
L’immagine è la ricetta congelata: un pacchetto immutabile che contiene un sistema operativo minimale, la versione esatta di Python che vuoi, le tue librerie e il tuo codice. È come un piatto pronto surgelato — sempre identico, lo puoi copiare e spedire, ma di per sé non «gira».
Il container è l’immagine messa in esecuzione: la ricetta scongelata e cucinata, un processo vivo isolato dal resto del tuo computer. Dalla stessa immagine puoi avviare dieci container identici, come dallo stesso surgelato puoi scaldare dieci porzioni. E qui il punto che sorprende chi inizia: quando il container si spegne, tutto ciò che ha prodotto al suo interno sparisce. È usa e getta per costruzione.
Il volume è la soluzione a quella sparizione: una cartella del tuo computer «vera» collegata a una cartella dentro il container, in modo che i dati la attraversino nei due sensi e sopravvivano allo spegnimento. È il cassetto della cucina che resta lì anche quando butti il contenitore d’alluminio: ci metti dentro i dati in ingresso e ci ritrovi i risultati in uscita.
Una sola immagine (la ricetta congelata) genera quanti container vuoi (le porzioni cucinate, usa e getta). Il volume è il cassetto esterno che collega una cartella del tuo computer al container, così dati e risultati non spariscono allo spegnimento.
Il codice da impacchettare
Partiamo da qualcosa di concreto: uno script che addestra un modello scikit-learn, ne stampa l’accuratezza e lo salva su disco. Niente di esotico — è proprio il genere di codice che oggi gira sul tuo laptop e domani vorresti far girare identico altrove. Crea una cartella di progetto e dentro un file train.py:
# train.py — addestra un classificatore e lo salva.
# Ambiente 2026: Python 3.12, scikit-learn moderno.
import joblib
from pathlib import Path
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
# I risultati vanno in /app/dati: dentro il container sara' un volume.
OUTPUT = Path("/app/dati")
OUTPUT.mkdir(parents=True, exist_ok=True)
X, y = load_wine(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Pipeline: scaling + modello, cosi' e' tutto in un oggetto solo.
modello = make_pipeline(
StandardScaler(),
RandomForestClassifier(n_estimators=200, random_state=42),
)
modello.fit(X_train, y_train)
accuratezza = modello.score(X_test, y_test)
print(f"Accuratezza sul test: {accuratezza:.4f}")
# Salviamo nel volume: questo file deve sopravvivere al container.
joblib.dump(modello, OUTPUT / "modello.joblib", compress=3)
print(f"Modello salvato in {OUTPUT / 'modello.joblib'}")
Accanto a train.py, un file requirements.txt che fissa le librerie. Il dettaglio importante è il pinning delle versioni: senza, tra sei mesi ricostruirai un’immagine con librerie diverse e il tuo «ambiente riproducibile» non lo sarà più.
# requirements.txt
scikit-learn==1.5.2
joblib==1.4.2
Il Dockerfile: la ricetta scritta
Il Dockerfile è il file che descrive come costruire l’immagine, riga per riga. Si legge come una ricetta: parti da una base, aggiungi ingredienti, dici cosa cucinare all’avvio. Crea un file chiamato Dockerfile (senza estensione) nella stessa cartella:
# Dockerfile — la ricetta della nostra immagine.
# 1. Base: Python 3.12 gia' pronto, versione "slim" (leggera).
FROM python:3.12-slim
# 2. Cartella di lavoro dentro il container.
WORKDIR /app
# 3. Prima copiamo SOLO i requirements e installiamo.
# Copiare le dipendenze separate dal codice sfrutta la cache:
# se cambi train.py ma non le librerie, Docker non reinstalla nulla.
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 4. Ora copiamo il codice vero e proprio.
COPY train.py .
# 5. Comando eseguito all'avvio del container.
CMD ["python", "train.py"]
L’ordine delle righe non è estetica: è la regola più utile del mestiere. Docker costruisce l’immagine a strati e ne mette in cache ciascuno; se cambi solo train.py, ricostruisce solo dall’ultimo COPY in giù, saltando la reinstallazione delle librerie. Mettere l’installazione prima del codice ti fa risparmiare minuti a ogni modifica.
Un’immagine Docker non è un backup del tuo computer: è la descrizione esatta e ripetibile dell’ambiente minimo in cui il tuo codice deve girare.
Build e run
Adesso i due comandi che userai il 90% delle volte. Il primo costruisce l’immagine dalla ricetta; il -t le dà un nome («tag»), il punto finale dice «il Dockerfile è in questa cartella»:
docker build -t vino-classifier .
Il secondo avvia un container da quell’immagine. Con --rm il container si autodistrugge appena finisce (così non ne accumuli cadaveri), e con -v montiamo il volume — la parte che rende utile tutto il resto:
docker run --rm -v "$(pwd)/dati:/app/dati" vino-classifier
Leggiamo il -v da sinistra a destra: $(pwd)/dati è la cartella dati/ nella tua directory attuale (sul tuo computer vero), /app/dati è la cartella dentro il container. I due punti le collegano. Lo script scrive in /app/dati/modello.joblib dentro il container, ma grazie al volume quel file compare in dati/modello.joblib sul tuo disco — e resta lì anche dopo che il container è sparito. Prova la controprova: lancia lo stesso comando senza il -v. Lo script gira, stampa l’accuratezza, salva il modello… e alla fine sul tuo computer non trovi niente. Il file è nato ed è morto dentro il container. È l’esperimento che fa scattare il concetto di volume una volta per tutte.
Onestà: quando serve e quando è troppo
Due avvertenze da amico. La prima: Docker non è una macchina virtuale e non è un backup. Non ci «entri dentro a lavorare» come in un secondo computer — quello è un antipattern che porta a immagini enormi e irriproducibili. L’immagine deve restare la descrizione minima di un ambiente, non una copia del tuo disco.
La seconda, più importante per te: non ti serve Docker per ogni cosa. Per esplorare un dataset in un notebook, per un’analisi che vive e muore sul tuo laptop, un ambiente virtuale con uv o venv è più leggero e più veloce, e va benissimo. Docker inizia a ripagare quando il codice deve uscire dal tuo computer: consegnarlo a un collega, farlo girare su un server, metterlo in una pipeline di produzione, garantire che tra un anno riparta identico. È il momento in cui «sul mio computer funziona» smette di essere accettabile — ed è lì che i tre concetti di oggi diventano indispensabili.
Prova tu
Modifica train.py per addestrare anche una LogisticRegression oltre alla foresta, e fai in modo che lo script salvi entrambi i modelli nel volume insieme a un piccolo file risultati.txt con le due accuratezze. Ricostruisci l’immagine con docker build e nota quanto è rapido: le librerie non vengono reinstallate, grazie alla cache degli strati che hai messo nell’ordine giusto. Poi lancia il container con il volume, apri la cartella dati/ sul tuo computer e verifica che ci siano i due .joblib e il risultati.txt. Se li trovi lì dopo che il container è già sparito, hai capito la parte che conta davvero: il codice è usa e getta, i dati no. Per andare oltre, la guida ufficiale Get started di Docker copre reti, Docker Compose e pubblicazione delle immagini — ma i tre concetti di oggi ti bastano per l’80% del lavoro quotidiano di un data scientist.
I commenti sono riservati agli iscritti.
Accedi per commentare