← Blogue

Les douze facteurs, sur un serveur que vous possédez

Railyard

1 juin 2026

La méthodologie de l’application douze-facteurs vient de la première équipe d’ingénierie de Heroku, décrivant les contraintes qu’une application web doit satisfaire pour bien tourner sur n’importe quelle plateforme moderne. Elle a survécu à la plateforme qui l’a produite, parce que les douze facteurs n’ont jamais vraiment été à propos de Heroku — ils sont à propos de ce qui rend un logiciel portable, évolutif et opérable, indépendamment de qui possède la machine en dessous. Voici où chacun apparaît réellement, concrètement, sur une plateforme construite autour de serveurs que vous possédez plutôt que vous louez.

I. Code source. Un dépôt, un déploiement — git push, ou la même URL Git collée dans le tableau de bord, reconstruit et redéploie à chaque push. Rien ici n’est spécifique à qui possède le serveur; c’est le même flux de travail que Heroku a popularisé, tournant sur une infrastructure dont vous détenez les clés.

II. Dépendances. Déclarées explicitement, jamais supposées de l’hôte : requirements.txt, Gemfile, package.json, go.mod, composer.json, mix.exs sont lus directement, et rien dans l’environnement de build ou d’exécution n’est supposé déjà installé globalement.

III. Configuration. Vit sous Variables, ou réglée avec railyard env:set my-app KEY=VALUE — jamais intégrée dans le build. Le même artefact tourne sans changement d’une branche de prévisualisation jusqu’à la production; un bug en staging est soit réel, soit il ne l’est pas, jamais un artefact d’un staging qui ferait tourner un bundle différent de la prod.

IV. Services externes. Une base de données, Redis, ou une autre application sur le canvas est référencée de la même façon qu’elle soit locale ou distante : ${{postgres.RAILYARD_PRIVATE_URL}}, résolue par environnement. Changez la ressource externe et le code de l’application n’a jamais besoin de le savoir.

V. Build, release, run. Trois étapes distinctes, pas une seule étape confuse : une méthode de build (Dockerfile en priorité s’il est présent, puis Railpack, Nixpacks, ou buildpacks) produit un artefact; une commande de release (php artisan migrate --force, python manage.py migrate --no-input, mix ecto.migrate) tourne une fois contre la nouvelle release avant que le trafic ne bouge; puis l’étape d’exécution la démarre réellement. Chaque étape peut échouer indépendamment, et le fait, plutôt qu’un seul script qui fait les trois et cache quelle partie a cassé.

VI. Processus. Sans état, et plus d’un type partageant un seul build : web, worker, scheduler, beat — chacun démarré avec une commande différente, chacun mis à l’échelle indépendamment (railyard scale my-app worker=2). Un seul code source, plusieurs rôles, jamais plusieurs code sources à garder synchronisés.

VII. Liaison au port. L’application se lie elle-même à $PORT et exporte HTTP comme un service — elle n’est pas injectée dans un conteneur d’exécution par magie. Un binaire Go, un processus Rails, une release Elixir compilée : tous se lient au même contrat $PORT, ce qui est la raison même pour laquelle la même méthode de build fonctionne à travers des langages complètement différents.

VIII. Concurrence. Évoluer en ajoutant des processus, pas en faisant faire plus à un seul : web=3 worker=2 sont deux dimensions mises à l’échelle indépendamment du même build, pas un exercice d’ajustement du nombre de threads dans un seul processus.

IX. Jetabilité. Démarrage rapide, arrêt propre, et une nouvelle release ne reçoit du trafic qu’une fois que son conteneur répond réellement — l’ancien continue de servir jusqu’à ce que le nouveau prouve qu’il est prêt, donc un mauvais déploiement n’a jamais de fenêtre où rien n’est en service.

X. Parité dev/prod. La seule règle qui apparaît, mot pour mot, dans la logique de détection propre à chaque framework sur cette plateforme : le même build tourne sans changement du premier push d’un développeur jusqu’au staging et à la production. Pas de « Dockerfile de production » séparé, pas de reconstruction spécifique à l’environnement — la parité n’est pas un objectif à viser, c’est le seul chemin qui existe.

XI. Les logs comme flux d’événements. L’application se contente d’écrire sur stdout/stderr; elle ne gère jamais ses propres fichiers de log. Ce que le conteneur imprime est ce qui apparaît en direct, ce qui est cherché plus tard, et ce qui est envoyé vers un drain — le travail de l’application se termine à l’impression, comme ça a toujours dû être le cas.

XII. Processus d’administration. Les tâches ponctuelles tournent dans exactement le même environnement que l’application en direct, pas dans une console maintenue séparément : railyard run my-app -- bin/rails db:migrate démarre un conteneur neuf depuis la release actuelle — la CLI elle-même emprunte le propre nom de Heroku pour la même idée (heroku run), parce que l’idée était déjà correcte.

Le vrai point de revisiter ceci maintenant

Aucune de ces douze règles n’exige de louer une infrastructure à qui les a écrites. Elles décrivent comment construire un logiciel qui ne se soucie pas de qui possède la machine sur laquelle il tourne — ce qui est exactement la propriété qui rend une application portable hors de n’importe quelle plateforme dès le départ, y compris celle-ci.

Référence complète : Méthodes de build, Variables et secrets, Documentation CLI.

Voyez une application douze-facteurs se déployer en temps réel.

Poussez un dépôt qui suit déjà ces règles — rien à ces règles ne change sur un serveur que vous possédez.

Offre gratuite, sans carte, et 14 jours de Pro pour chaque nouvelle équipe. Prix fixe par équipe.