Alternatives à Docker Compose
Docker Compose n'est pas un mauvais outil, et la plupart des systèmes qui le dépassent n'ont jamais eu la forme pour laquelle il a été pensé. Cette page parle du moment où il cesse de payer, et de ce à quoi chaque alternative renonce vraiment —y compris la nôtre, qui n'est pas la bonne réponse pour tout le monde—.
Quand Compose reste la réponse
Si votre environnement local, c'est « une base de données, une file et deux services », Compose est un fichier que vous écrivez une fois et que vous oubliez. Il est partout, tout le monde lit du YAML et il n'y a pas besoin qu'un nouvel outil entre dans l'équipe. Ne le remplacez pas par mode.
Où ça commence à faire mal
- Votre code doit être une image. Chaque changement signifie reconstruire, ou un bind mount plus une astuce de rechargement par langage, inventée une fois dans chaque dépôt.
- C'est tout ou rien. Compose lève ce que dit le fichier. Pour lever trois services et pointer le reste vers un environnement partagé, vous éditez le fichier ou vous en maintenez plusieurs.
- Déboguer est une corvée. Un débogueur face à un conteneur demande un port, un mappage et une configuration d'IDE que quelqu'un doit maintenir en vie.
- Le fichier se périme. Il vit dans un dépôt, décrit des services qui appartiennent à d'autres, et le maintenir n'est le travail de personne.
- Il ne sait rien de la santé.
depends_onattend un conteneur, pas un service prêt à répondre.
Le même environnement, des deux côtés
Voici la forme que prend un docker-compose.yml d'un petit système —deux
services et leur infrastructure— quand quelqu'un s'est déjà battu avec la boucle de
changement :
services:
postgres:
image: postgres:16
environment: { POSTGRES_PASSWORD: dev }
ports: ['5432:5432']
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 5s
kafka:
image: bitnami/kafka:3.7
environment:
KAFKA_CFG_NODE_ID: '0'
KAFKA_CFG_PROCESS_ROLES: controller,broker
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093
ports: ['9092:9092']
orders:
build: ../orders # reconstruire à chaque changement
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/orders
PAYMENTS_URL: http://payments:8081
SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092
ports: ['8080:8080', '5005:5005'] # le second, pour le débogueur
depends_on:
postgres: { condition: service_healthy }
payments:
build: ../payments
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/payments
ports: ['8081:8081']
Ça marche. Ce qui coûte n'est pas dans le fichier, c'est autour : chaque changement
dans orders passe par un build ; le port 5005 doit être
convenu, mappé et configuré dans l'IDE de chacun ; PAYMENTS_URL est
écrit à la main et pointer payments vers le cloud signifie éditer le
fichier (et penser à ne pas le committer) ; et ce fichier vit dans un dépôt qui n'est
pas celui de payments, donc personne ne le met à jour quand
payments change de variable.
L'équivalent chez Aseptic n'est pas un autre fichier comme celui-ci : c'est que les
services ne sont pas empaquetés. orders et payments
démarrent comme des processus, avec le rechargement à chaud que leur framework apporte
déjà et le débogueur attaché comme à n'importe quel processus local. La seule chose
qui reste dans Docker, c'est l'infrastructure —Postgres et Kafka—, levée par l'app qui
remappe ses ports s'ils sont occupés. Et les URL entre services ne s'écrivent pas :
elles sont injectées au démarrage, selon où vous avez pointé chaque dépendance.
orders ← processus local, port 8080
├── postgres → infrastructure dans Docker (levée par Aseptic)
├── kafka → infrastructure dans Docker
└── payments → local | cloud | mock ← ça se change d'un clic
Le changement qui compte est celui de la dernière ligne. Dans Compose, « aujourd'hui
je veux payments contre l'environnement cloud » signifie éditer du YAML ;
ici c'est changer la cible d'une dépendance, et le reste du scénario s'en aperçoit
tout seul. Et rien de tout cela ne se range dans vos dépôts : le scénario vit dehors,
il n'y a donc aucun fichier d'environnement à relire dans une pull request.
Les alternatives, honnêtement
| Outil | Ce que c'est en réalité | Coût d'entrée |
|---|---|---|
| Tilt | Une boucle interne rapide face à Kubernetes, avec une interface qui montre builds, logs et santé | Un cluster, des images et un Tiltfile par dépôt |
| Skaffold | Build, push et deploy vers Kubernetes en une seule commande, avec des profils | Un cluster, des images, des manifestes et un skaffold.yaml |
| DevSpace | Votre code tournant dans un conteneur de développement du cluster, avec synchronisation de fichiers | Un cluster, et être à l'aise pour déboguer de l'autre côté |
| Garden | Un graphe de dépendances pour construire, déployer et tester, partagé par le dev et la CI | Une décision de plateforme, et quelqu'un qui prenne le graphe en charge |
| Telepresence | Un processus local inséré dans un vrai cluster en interceptant son trafic | Un cluster partagé sain, et de la connectivité jusqu'à lui |
| Kubernetes local (kind, minikube) | Les vraies primitives sur votre machine, pour que ce que vous testez ait la forme de la production | De la mémoire, et le cycle de déploiement à chaque changement |
| Aseptic | Des services en processus natifs, chaque dépendance pointée vers local, cloud ou un mock | L'installer ; Docker seulement pour l'infrastructure commune |
Le motif derrière la liste
Cinq des sept répondent à « Compose ne suffit pas » par « alors utilisez Kubernetes en local ». C'est une réponse cohérente, et si vous déployez sur Kubernetes elle vous achète une ressemblance qu'aucune autre ne donne. Elle importe aussi le cycle construire-et-déployer du cluster dans la boucle que vous répétez deux cents fois par jour.
Aseptic est l'intrus de la liste, et c'est délibéré : il part du principe que vous ne voulez pas d'un cluster sur votre machine pour tester un flux. Vos services tournent comme des processus, l'infrastructure commune —Kafka, Redis, PostgreSQL— vous est levée dans Docker, et chaque dépendance se résout vers un service local, vers votre environnement cloud partagé ou vers un mock, avec les URL réécrites au démarrage pour ne toucher aucun dépôt.
Là où Aseptic est le mauvais choix
Si ce que vous devez tester, c'est la partie Kubernetes —ingress, network policies, sidecars, probes, limites de ressources— Aseptic n'exécute rien de tout cela et ne vous sert à rien. Si vos services ne démarrent que dans un namespace préparé, les exécuter dehors n'est pas un raccourci : c'est une réécriture. Et si la vérification quotidienne que vos images et vos manifestes marchent encore vaut pour vous plus qu'une boucle rapide, cela vous est donné par Skaffold ou Tilt, pas par Aseptic.
Il est de plus en bêta publique, publié pour Windows, macOS et Linux, et il n'est pas open source. Tous les autres outils de cette liste sont open source, et pour certaines équipes cela tranche déjà tout.
Comment choisir sans tableur
- Vos services démarrent-ils avec des variables d'environnement et une base de données ? Si oui, les exécuter en natif est la boucle la moins chère que vous puissiez avoir.
- Testez-vous votre code ou votre déploiement ? Votre code n'a pas besoin d'un cluster. Votre déploiement n'a besoin de rien d'autre.
- Le système tient-il sur une machine ? S'il ne tient vraiment pas, Telepresence ou un cluster partagé est la réponse honnête.
- Qui maintient la configuration ? Un outil dont la configuration n'appartient à personne sera abandonné en deux trimestres, quel que soit votre choix.
Le comparatif général met Docker Compose, un Kubernetes local et Aseptic côte à côte avec plus de détail.
Questions fréquentes
Quelle est l'alternative à Docker Compose pour les microservices ?
Cela dépend de ce qui vous coûte. Si c'est la ressemblance à la production, un Kubernetes local avec Tilt ou Skaffold ; si c'est la boucle quotidienne de travailler sur plusieurs services, un orchestrateur local. Cette page compare les cinq approches et là où chacune casse.
Docker Compose est-il insuffisant pour les microservices ?
Pas pour l'infrastructure, qui est ce qu'il fait le mieux. Il devient insuffisant quand ce sont vos services qui sont dans le fichier compose : une image à construire à chaque changement, pas de rechargement à chaud confortable, et la communication entre eux câblée à la main.
Y a-t-il une option qui n'ait pas besoin de Kubernetes ?
Oui : rester sur Compose, ou un orchestrateur local comme Aseptic, qui utilise Docker pour l'infrastructure et exécute vos services comme des processus de la machine.