Dockerfile vs buildpacks : lequel choisir pour votre app ?
En bref
- Avec un Dockerfile, vous écrivez vous-même chaque étape du build ; les Cloud Native Buildpacks détectent votre langage et construisent l'image à partir de votre code source, sans Dockerfile.
- Les buildpacks conviennent aux apps standard dans les langages pris en charge et laissent la maintenance de l'image de base au builder ; un Dockerfile convient aux paquets système spécifiques, aux stacks atypiques et au contrôle total de l'image.
- Les deux produisent une image de conteneur : vous pouvez commencer avec l'un et changer plus tard.
- Sur Nodion, vous choisissez Buildpacks ou Dockerfile pour chaque app : les apps buildpacks écoutent sur le PORT défini par Nodion, les apps Dockerfile sur le port issu de EXPOSE ou de l'onglet Processes.
Un Dockerfile et des buildpacks transforment tous deux votre code source en image de conteneur. La différence tient à la définition des étapes du build : avec un Dockerfile, vous les écrivez ; avec des buildpacks, elles sont déduites de votre code. Utilisez des buildpacks pour une app web standard dans un langage pris en charge, et un Dockerfile quand vous avez besoin d'un contrôle total sur l'image ou que vous utilisez une stack qu'aucun buildpack ne détecte.
Qu'est-ce qu'un Dockerfile ?
Selon les propres termes de Docker, un Dockerfile est « a text document that contains all the commands a user could call on the command line to assemble an image », autrement dit un document texte qui contient toutes les commandes qu'un utilisateur pourrait lancer en ligne de commande pour assembler une image. Vous choisissez une image de base, installez des paquets système, copiez votre code, installez les dépendances et définissez la commande de démarrage. Vous définissez chaque ligne : vous gardez le contrôle, mais devez aussi tout maintenir.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"] Deux fonctionnalités déterminent la façon dont on écrit un Dockerfile en pratique :
- Cache des couches : l'image est construite par couches (layers), et Docker les met en cache. Quand une couche change, toutes les couches suivantes sont reconstruites aussi. C'est pourquoi l'exemple copie
package.jsonet installe les dépendances avant de copier le reste du code. - Builds multi-stage : plusieurs instructions
FROMdans un même fichier, chacune ouvrant une nouvelle étape. Vous compilez dans une étape et ne copiez que le résultat dans une petite image finale, en laissant de côté les compilateurs et les outils de build.
Que sont les buildpacks ?
Un buildpack est un logiciel qui analyse votre code source et détermine comment le construire. Les Cloud Native Buildpacks sont le standard ouvert pour cela. Un build passe par des phases fixes : detect trouve les buildpacks qui correspondent à votre code, build transforme les sources en artefacts exécutables (par exemple en installant un runtime et les dépendances, puis en compilant), et export écrit l'image OCI finale. Vous n'avez pas besoin de Dockerfile ; des fichiers optionnels comme un Procfile ou project.toml permettent de configurer le build et les processus.
Trois propriétés distinguent les buildpacks :
- Images de build et d'exécution séparées : les compilateurs et les fichiers d'en-tête restent dans l'image de build, et l'app est exécutée à partir de l'image d'exécution (run image), sans eux.
- Rebase : quand l'image d'exécution reçoit une mise à jour,
pack rebasefait pointer l'image de l'app vers la nouvelle base sans refaire le build de l'app. - Reproductibilité : le lifecycle fixe l'horodatage des couches à une date constante : les mêmes sources, le même builder et les mêmes buildpacks produisent donc la même image, à condition que les buildpacks eux-mêmes produisent un résultat reproductible.
Pour en savoir plus, lisez Les Cloud Native Buildpacks expliqués.
Dockerfile vs buildpacks en un coup d'œil
| Dockerfile | Buildpacks | |
|---|---|---|
| Contrôle | Total : image de base, paquets, utilisateurs, organisation des fichiers | Dans les limites des options du buildpack : versions verrouillées, Procfile, paquets supplémentaires |
| Maintenance | Vous mettez à jour l'image de base et chaque étape | Le mainteneur du builder met à jour la stack et les buildpacks de langage |
| Mises à jour de sécurité | Nouveau build avec une image de base corrigée ; à vous de repérer les correctifs | Les mises à jour du builder apportent des images de base corrigées au build suivant ; une image existante nécessite un nouveau build ou un rebase explicite |
| Reproductibilité | Dépend de la rigueur avec laquelle vous fixez les images et les paquets | Intégrée pour des entrées identiques, avec des horodatages de couches fixes |
| Vitesse de build | Rapide avec un cache de couches bien ordonné ; un changement en début de fichier reconstruit tout ce qui suit | Les couches en cache, comme les dépendances, sont restaurées d'un build à l'autre |
| Multi-stage | Oui, plusieurs étapes FROM | Inutile : les outils de build restent dans l'image de build |
| Stacks atypiques | Tout ce que vous pouvez installer dans une image | Uniquement ce que le builder détecte |
Quand choisir des buildpacks
- Votre app est écrite dans un langage pris en charge par le builder, comme Node.js, Python, Ruby, PHP, Go, Rust, Java, .NET ou Elixir, ou c'est un site statique.
- Vous ne voulez pas maintenir vous-même les images de base et les paquets du système d'exploitation.
- Vous faites tourner de nombreux services et voulez qu'ils soient tous construits de la même façon.
- Votre équipe connaît le langage, pas Docker.
Quand choisir un Dockerfile
- Vous avez besoin d'une image de base précise, de paquets système au-delà de ce qu'installe un buildpack, ou d'un utilisateur personnalisé.
- Votre langage ou votre framework n'est pas détecté par le builder.
- Le projet fournit déjà un Dockerfile fonctionnel, comme beaucoup d'apps open source.
- Vous voulez une image minuscule grâce à un build multi-stage, ou exactement la même image en local, en CI et en production.
Comment Nodion prend en charge les deux
Sous Applications → New, vous connectez un dépôt Git et choisissez Buildpacks ou Dockerfile. L'analyse privilégie le Dockerfile quand elle en trouve un. Vous pouvez changer de stratégie plus tard dans Settings ; le changement s'applique au déploiement suivant. Si vous faites vos builds ailleurs, déployez plutôt une image préconstruite.
Les buildpacks sur Nodion
- Les Cloud Native Buildpacks de Nodion, sur la stack
nodion-26(Ubuntu 26.04 LTS). Ils détectent Node.js, Python, Ruby, PHP, Go, Rust, Elixir, Java, .NET et les sites statiques. - Le processus tourne sous un utilisateur non root. Les paquets Debian supplémentaires se déclarent dans
project.tomlou unAptfile; leurs scripts de mainteneur ne s'exécutent pas. - Un
Procfiledéfinit les types de processus ; sinon, une valeur par défaut du langage définit le processusweb. - Port : Nodion définit
PORT. Écoutez sur ce port ; la plupart des commandes par défaut se rabattent sur 8080 s'il n'est pas défini.
web: gunicorn myapp.wsgi --bind 0.0.0.0:$PORT
worker: python worker.py Le Dockerfile sur Nodion
- Le paramètre Base directory sert de contexte de build, et un
.dockerignorequi s'y trouve est pris en compte. - Les fichiers multi-stage fonctionnent. Il n'y a pas de sélecteur d'étape : c'est donc la dernière étape qui tourne.
- Les variables d'environnement marquées Build sont transmises comme build args (
ARG). Les secrets BuildKit ne sont pas transmis. - Port : Nodion ne définit pas
PORTpour une app Dockerfile. Liez votre app au port du processus web, prérempli à partir deEXPOSEet modifiable dans l'onglet Processes ; si cette liste est vide, Nodion utilise leEXPOSEde l'image, puis 8080. Écoutez sur toutes les interfaces, pas seulement sur localhost. - Health check : la disponibilité (readiness) est vérifiée par un HTTP GET sur le chemin du health check défini dans Settings (par défaut
/). Une réponse 2xx ou 3xx signifie que l'app est saine. UnHEALTHCHECKdans l'image est ignoré. - Le
USERde l'image est respecté.
Tous les détails se trouvent dans la documentation des buildpacks et la documentation Dockerfile. Vous hésitez encore ? Commencez avec les buildpacks, et ajoutez un Dockerfile le jour où vous aurez besoin de quelque chose qu'ils ne savent pas faire.
Questions fréquentes
Ai-je besoin d'un Dockerfile pour déployer un conteneur ?
Non. Les buildpacks construisent une image de conteneur directement à partir de votre code source, sans Dockerfile dans le dépôt. Vous pouvez aussi déployer une image préconstruite depuis un registry.
Les buildpacks sont-ils meilleurs qu'un Dockerfile ?
Aucun des deux n'est meilleur dans l'absolu. Les buildpacks demandent moins de maintenance pour les apps standard dans les langages pris en charge, tandis qu'un Dockerfile vous donne un contrôle total sur l'image et fonctionne avec n'importe quelle stack.
Puis-je utiliser un Dockerfile multi-stage sur Nodion ?
Oui. Les Dockerfiles multi-stage fonctionnent. Il n'y a pas de sélecteur d'étape : c'est donc la dernière étape qui constitue l'image exécutée.
Sur quel port mon app doit-elle écouter ?
Avec les buildpacks, écoutez sur la variable d'environnement PORT définie par Nodion. Avec un Dockerfile, Nodion ne définit pas PORT : liez votre app au port du processus web, repris de EXPOSE ou défini dans l'onglet Processes, et écoutez sur toutes les interfaces.