Dockerfile vs buildpack: quale usare per la tua app?
In breve
- Con un Dockerfile scrivi tu ogni passaggio della build; i Cloud Native Buildpacks riconoscono il tuo linguaggio e costruiscono l'immagine dal codice sorgente senza Dockerfile.
- I buildpack sono adatti alle app standard in linguaggi supportati e lasciano al builder la manutenzione dell'immagine di base; un Dockerfile è adatto a pacchetti di sistema personalizzati, stack insoliti e pieno controllo sull'immagine.
- Entrambi producono un'immagine container, quindi puoi partire con uno e cambiare in seguito.
- Su Nodion scegli Buildpack o Dockerfile per ogni app: le app con buildpack sono in ascolto sulla PORT impostata da Nodion, quelle con Dockerfile sulla porta di EXPOSE o della scheda Processes.
Sia un Dockerfile sia i buildpack trasformano il tuo codice sorgente in un'immagine container. La differenza è chi definisce i passaggi della build: con un Dockerfile lo fai tu, con i buildpack vengono ricavati dal tuo codice. Usa i buildpack per una normale web app in un linguaggio supportato e un Dockerfile quando ti serve il pieno controllo sull'immagine o usi uno stack che nessun buildpack riconosce.
Cos'è un Dockerfile
Con le parole di Docker, un Dockerfile è “a text document that contains all the commands a user could call on the command line to assemble an image”, cioè un documento di testo con tutti i comandi che un utente potrebbe eseguire dalla riga di comando per assemblare un'immagine. Scegli un'immagine di base, installi i pacchetti di sistema, copi il tuo codice, installi le dipendenze e imposti il comando di avvio. Ogni riga è tua: pieno controllo, ma anche tutta la manutenzione.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"] Nella pratica, due funzionalità determinano come si scrivono i Dockerfile:
- Cache dei layer: l'immagine viene costruita a layer, e Docker li mette in cache. Quando un layer cambia, vengono ricostruiti anche tutti i layer successivi. Per questo l'esempio copia
package.jsone installa le dipendenze prima di copiare il resto del codice. - Build multi-stage: più istruzioni
FROMin un solo file, ognuna delle quali avvia un nuovo stage. Compili in uno stage e copi solo il risultato in un'immagine finale piccola, lasciandoti alle spalle compilatori e strumenti di build.
Cosa sono i buildpack
Un buildpack è un software che analizza il tuo codice sorgente e capisce come farne la build. I Cloud Native Buildpacks sono lo standard aperto per farlo. Una build attraversa fasi fisse: detect trova i buildpack adatti al tuo codice, build trasforma il sorgente in artefatti eseguibili (per esempio installando un runtime e le dipendenze e compilando), ed export scrive l'immagine OCI finale. Non ti serve un Dockerfile; file opzionali come un Procfile o project.toml possono configurare la build e i processi.
Tre proprietà distinguono i buildpack:
- Immagini di build e di runtime separate: compilatori e header stanno nell'immagine di build, e l'app viene distribuita sull'immagine di runtime senza di essi.
- Rebase: quando l'immagine di runtime riceve un aggiornamento,
pack rebasefa puntare l'immagine dell'app alla nuova base senza rifare la build dell'app. - Riproducibilità: il lifecycle imposta i timestamp dei layer a una data fissa, quindi lo stesso sorgente, lo stesso builder e gli stessi buildpack producono la stessa immagine, a patto che i buildpack stessi producano un output riproducibile.
Trovi altri dettagli in Cloud Native Buildpacks: cosa sono e come funzionano.
Dockerfile vs buildpack in sintesi
| Dockerfile | Buildpack | |
|---|---|---|
| Controllo | Totale: immagine di base, pacchetti, utenti, struttura dei file | Entro le opzioni del buildpack: pin di versione, Procfile, pacchetti aggiuntivi |
| Manutenzione | Aggiorni tu l'immagine di base e ogni passaggio | Chi mantiene il builder aggiorna lo stack e i pacchetti dei linguaggi |
| Aggiornamenti di sicurezza | Rifai la build con un'immagine di base aggiornata; devi accorgertene tu | Gli aggiornamenti del builder portano immagini di base aggiornate alla build successiva; un'immagine esistente richiede una nuova build o un rebase esplicito |
| Riproducibilità | Dipende da quanto rigorosamente fissi immagini e pacchetti | Integrata a parità di input, con timestamp dei layer fissi |
| Velocità di build | Veloce con una cache dei layer ben ordinata; una modifica all'inizio ricostruisce tutto ciò che segue | I layer in cache, come le dipendenze, vengono ripristinati tra una build e l'altra |
| Multi-stage | Sì, più stage FROM | Non serve: gli strumenti di build restano nell'immagine di build |
| Stack insoliti | Tutto ciò che puoi installare in un'immagine | Solo ciò che il builder riconosce |
Quando scegliere i buildpack
- La tua app è scritta in un linguaggio supportato dal builder, come Node.js, Python, Ruby, PHP, Go, Rust, Java, .NET o Elixir, oppure è un sito statico.
- Non vuoi gestire da solo immagini di base e pacchetti del sistema operativo.
- Hai molti servizi e vuoi che vengano tutti costruiti allo stesso modo.
- Il tuo team conosce il linguaggio, non Docker.
Quando scegliere un Dockerfile
- Ti serve un'immagine di base specifica, pacchetti di sistema oltre a quelli che installa un buildpack, o un utente personalizzato.
- Il tuo linguaggio o framework non viene riconosciuto dal builder.
- Il progetto include già un Dockerfile funzionante, come molte app open source.
- Vuoi un'immagine piccola da una build multi-stage, oppure esattamente la stessa immagine in locale, in CI e in produzione.
Come Nodion supporta entrambi
In Applications → New colleghi un repository Git e scegli Buildpacks o Dockerfile. La scansione preferisce Dockerfile quando ne trova uno. Puoi cambiare la strategia in seguito in Settings; si applica dal deploy successivo. Se fai la build altrove, fai invece il deploy di un'immagine già pronta.
Buildpack su Nodion
- I Cloud Native Buildpacks di Nodion sullo stack
nodion-26(Ubuntu 26.04 LTS). Riconoscono Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET e siti statici. - Il processo gira come utente non root. I pacchetti Debian aggiuntivi vanno in
project.tomlo in unAptfile; i loro script di manutenzione non vengono eseguiti. - Un
Procfiledefinisce i tipi di processo; altrimenti, l'impostazione predefinita del linguaggio imposta il processoweb. - Porta: Nodion imposta
PORT. Mettiti in ascolto su quella porta; se non è impostata, la maggior parte dei comandi predefiniti ripiega su 8080.
web: gunicorn myapp.wsgi --bind 0.0.0.0:$PORT
worker: python worker.py Dockerfile su Nodion
- La base directory è il build context, e un
.dockerignoreal suo interno viene rispettato. - I file multi-stage funzionano. Non c'è un selettore di stage, quindi viene eseguito l'ultimo stage.
- Le variabili d'ambiente contrassegnate come Build vengono passate come build arg (
ARG). I secret di BuildKit non sono collegati. - Porta: Nodion non imposta
PORTsu un'app con Dockerfile. Mettiti in ascolto sulla porta del processo web, precompilata daEXPOSEe modificabile nella scheda Processes; se quella lista è vuota, Nodion usa la porta indicata daEXPOSEnell'immagine, poi 8080. Ascolta su tutte le interfacce, non solo su localhost. - Health check: la readiness è una richiesta HTTP GET al percorso dell'health check indicato in Settings (per impostazione predefinita
/). Una risposta 2xx o 3xx indica che l'app è pronta. UnHEALTHCHECKnell'immagine viene ignorato. - L'istruzione
USERdell'immagine viene rispettata.
Tutti i dettagli sono in Buildpack e nella documentazione del Dockerfile. Non sei ancora sicuro? Parti con i buildpack e aggiungi un Dockerfile quando ti serve qualcosa che non possono fare.
Domande frequenti
Mi serve un Dockerfile per fare il deploy di un container?
No. I buildpack costruiscono un'immagine container direttamente dal tuo codice sorgente, senza un Dockerfile nel repository. Puoi anche fare il deploy di un'immagine già pronta da un registry.
I buildpack sono meglio di un Dockerfile?
Nessuno dei due è migliore in assoluto. I buildpack richiedono meno manutenzione per le app standard in linguaggi supportati, mentre un Dockerfile ti dà il pieno controllo sull'immagine e funziona con qualsiasi stack.
Posso usare un Dockerfile multi-stage su Nodion?
Sì. I Dockerfile multi-stage funzionano. Non c'è un selettore di stage, quindi l'immagine che gira è quella dell'ultimo stage.
Su quale porta deve stare in ascolto la mia app?
Con i buildpack, sulla variabile d'ambiente PORT che Nodion imposta. Con un Dockerfile, Nodion non imposta PORT: mettiti in ascolto sulla porta del processo web, presa da EXPOSE o impostata nella scheda Processes, e su tutte le interfacce.