Dockerfile vs buildpacks: welke gebruik je voor je app?
In het kort
- In een Dockerfile schrijf je elke buildstap zelf; Cloud Native Buildpacks herkennen je taal en bouwen de image zonder Dockerfile uit je broncode.
- Buildpacks passen bij standaardapps in ondersteunde talen en laten het onderhoud van de basisimage aan de builder over; een Dockerfile past bij specifieke systeempakketten, ongebruikelijke stacks en volledige controle over de image.
- Beide leveren een containerimage op. Je kunt dus met een van beide beginnen en later overstappen.
- Op Nodion kies je per app Buildpacks of Dockerfile: buildpacks-apps luisteren op de PORT die Nodion instelt, Dockerfile-apps op de poort uit EXPOSE of het tabblad Processes.
Een Dockerfile en buildpacks maken allebei van je broncode een containerimage. Het verschil zit in wie de buildstappen bepaalt: bij een Dockerfile doe jij dat, bij buildpacks worden ze uit je code afgeleid. Kies buildpacks voor een standaard webapp in een ondersteunde taal, en een Dockerfile als je volledige controle over de image nodig hebt of een stack draait die geen enkel buildpack herkent.
Wat een Dockerfile is
In de woorden van Docker zelf is een Dockerfile “a text document that contains all the commands a user could call on the command line to assemble an image”: een tekstbestand met alle commando's die een gebruiker op de commandoregel zou kunnen uitvoeren om een image samen te stellen. Je kiest een basisimage, installeert systeempakketten, kopieert je code, installeert dependencies en stelt het startcommando in. Elke regel is van jou: volledige controle, maar ook volledig onderhoud.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"] Twee eigenschappen bepalen hoe je in de praktijk een Dockerfile schrijft:
- Layercache: de image wordt in layers gebouwd en Docker cachet die layers. Verandert er een layer, dan wordt elke layer daarna ook opnieuw gebouwd. Daarom kopieert het voorbeeld eerst
package.jsonen installeert het de dependencies voordat het de rest van de code kopieert. - Multi-stage builds: meerdere
FROM-instructies in één bestand, die elk een nieuwe stage starten. Je compileert in de ene stage en kopieert alleen het resultaat naar een kleine uiteindelijke image; compilers en buildtools blijven in de eerdere stage achter.
Wat buildpacks zijn
Een buildpack is software die je broncode analyseert en bepaalt hoe die gebouwd moet worden. Cloud Native Buildpacks zijn daarvoor de open standaard. Een build doorloopt vaste fasen: detect vindt de buildpacks die bij je code passen, build zet de broncode om in uitvoerbare bestanden (bijvoorbeeld door een runtime en dependencies te installeren en te compileren), en export schrijft de uiteindelijke OCI-image. Je hebt geen Dockerfile nodig; met optionele bestanden zoals een Procfile of project.toml configureer je de build en de processen.
Drie eigenschappen onderscheiden buildpacks:
- Aparte build- en run-images: compilers en headers zitten in de build-image, en de app draait op de run-image zonder die tools.
- Rebase: krijgt de run-image een update, dan gebruikt de app-image via
pack rebasede nieuwe basis zonder dat je de app opnieuw bouwt. - Reproduceerbaarheid: de lifecycle zet de tijdstempels van de layers op een vaste datum, zodat dezelfde broncode, builder en buildpacks dezelfde image opleveren, zolang de buildpacks zelf reproduceerbare output leveren.
Meer achtergrond lees je in Cloud Native Buildpacks uitgelegd.
Dockerfile vs buildpacks in één oogopslag
| Dockerfile | Buildpacks | |
|---|---|---|
| Controle | Volledig: basisimage, pakketten, gebruikers, bestandsindeling | Binnen de opties van het buildpack: vastgepinde versies, Procfile, extra pakketten |
| Onderhoud | Je werkt de basisimage en elke stap zelf bij | De beheerder van de builder werkt de stack en de taalbuildpacks bij |
| Beveiligingsupdates | Opnieuw bouwen met een gepatchte basisimage; je moet het zelf in de gaten houden | Updates van de builder brengen gepatchte basisimages naar de volgende build; een bestaande image heeft een nieuwe build of een expliciete rebase nodig |
| Reproduceerbaarheid | Hangt af van hoe strikt je images en pakketten vastpint | Ingebouwd bij dezelfde input, met vaste tijdstempels voor layers |
| Buildsnelheid | Snel met een goed geordende layercache; een vroege wijziging bouwt alles daarna opnieuw | Gecachete layers, zoals dependencies, worden tussen builds hersteld |
| Multi-stage | Ja, meerdere FROM-stages | Niet nodig: buildtools blijven in de build-image |
| Ongebruikelijke stacks | Alles wat je in een image kunt installeren | Alleen wat de builder herkent |
Wanneer kies je buildpacks
- Je app is geschreven in een taal die de builder ondersteunt, zoals Node.js, Python, Ruby, PHP, Go, Rust, Java, .NET of Elixir, of het is een statische site.
- Je wilt basisimages en OS-pakketten niet zelf onderhouden.
- Je draait veel services en wilt ze allemaal op dezelfde manier bouwen.
- Je team kent de taal, maar Docker niet.
Wanneer kies je een Dockerfile
- Je hebt een specifieke basisimage nodig, systeempakketten buiten wat een buildpack installeert, of een eigen gebruiker.
- Je taal of framework wordt niet door de builder herkend.
- Het project levert al een werkende Dockerfile mee, zoals veel open source apps.
- Je wilt een piepkleine image uit een multi-stage build, of precies dezelfde image lokaal, in CI en in productie.
Hoe Nodion beide ondersteunt
Bij Applications → New koppel je een Git-repository en kies je Buildpacks of Dockerfile. Vindt de scan een Dockerfile, dan krijgt Dockerfile de voorkeur. Je kunt de strategie later wijzigen in Settings; de wijziging geldt vanaf de volgende deploy. Bouw je ergens anders, deploy dan in plaats daarvan een vooraf gebouwde image.
Buildpacks op Nodion
- De eigen Cloud Native Buildpacks van Nodion op de stack
nodion-26(Ubuntu 26.04 LTS). Ze herkennen Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET en statische sites. - Het proces draait als gebruiker zonder rootrechten. Extra Debian-pakketten zet je in
project.tomlof eenAptfile; hun maintainerscripts worden niet uitgevoerd. - Een
Procfiledefinieert de procestypen; anders bepaalt een standaardwaarde voor de taal hetweb-proces. - Poort: Nodion stelt
PORTin. Luister daarop; de meeste standaardcommando's vallen terug op 8080 als die variabele niet is ingesteld.
web: gunicorn myapp.wsgi --bind 0.0.0.0:$PORT
worker: python worker.py Dockerfile op Nodion
- De instelling Base directory bepaalt de buildcontext; een
.dockerignoredaarin wordt gerespecteerd. - Multi-stage-bestanden werken. Er is geen stagekiezer, dus de laatste stage is wat draait.
- Omgevingsvariabelen die als Build zijn gemarkeerd, worden doorgegeven als build args (
ARG). BuildKit-secrets worden niet doorgegeven. - Poort: Nodion stelt bij een Dockerfile-app geen
PORTin. Laat je app luisteren op de poort van het webproces. Die wordt vooraf ingevuld op basis vanEXPOSEen kun je wijzigen op het tabblad Processes. Is die lijst leeg, dan gebruikt Nodion deEXPOSEvan de image en daarna 8080. Luister op alle interfaces, niet alleen op localhost. - Health check: readiness wordt gecontroleerd met een HTTP GET naar het pad voor de health check in Settings (standaard
/). Een 2xx- of 3xx-respons betekent gezond. EenHEALTHCHECKin de image wordt genegeerd. - De
USERvan de image wordt gerespecteerd.
Alle details staan in de buildpacks-documentatie en de Dockerfile-documentatie. Twijfel je nog? Begin met buildpacks en voeg een Dockerfile toe op de dag dat je iets nodig hebt wat ze niet kunnen.
Veelgestelde vragen
Heb ik een Dockerfile nodig om een container te deployen?
Nee. Buildpacks bouwen een containerimage rechtstreeks uit je broncode, zonder Dockerfile in de repository. Je kunt ook een vooraf gebouwde image uit een registry deployen.
Zijn buildpacks beter dan een Dockerfile?
Geen van beide is in het algemeen beter. Buildpacks vragen minder onderhoud voor standaardapps in ondersteunde talen, terwijl een Dockerfile je volledige controle over de image geeft en met elke stack werkt.
Kan ik een multi-stage Dockerfile gebruiken op Nodion?
Ja. Multi-stage Dockerfiles werken. Er is geen stagekiezer, dus de laatste stage is de image die draait.
Op welke poort moet mijn app luisteren?
Met buildpacks luister je op de omgevingsvariabele PORT die Nodion instelt. Met een Dockerfile stelt Nodion geen PORT in: bind aan de poort van het webproces, overgenomen uit EXPOSE of ingesteld op het tabblad Processes, en luister op alle interfaces.