Docker-Compose-Alternativen
Docker Compose ist kein schlechtes Werkzeug, und die meisten Systeme, denen es zu klein wird, hatten nie die Form, für die es gedacht war. Diese Seite handelt von dem Punkt, an dem es aufhört sich zu lohnen, und davon, worauf jede Alternative wirklich verzichtet —unsere eingeschlossen, die nicht für jeden die richtige Antwort ist—.
Wann Compose weiterhin die Antwort ist
Wenn deine lokale Umgebung „eine Datenbank, eine Queue und zwei Services“ ist, ist Compose eine Datei, die du einmal schreibst und vergisst. Es ist überall, alle lesen YAML, und es muss kein neues Werkzeug ins Team. Ersetze es nicht aus Mode.
Wo es anfängt weh zu tun
- Dein Code muss ein Image sein. Jede Änderung bedeutet neu bauen, oder ein Bind Mount plus ein Reload-Trick pro Sprache, einmal in jedem Repository neu erfunden.
- Es ist alles oder nichts. Compose startet, was die Datei sagt. Um drei Services zu starten und den Rest auf eine gemeinsame Umgebung zeigen zu lassen, änderst du die Datei oder pflegst mehrere.
- Debuggen ist Mühe. Ein Debugger gegen einen Container braucht einen Port, ein Mapping und eine IDE-Konfiguration, die jemand am Leben halten muss.
- Die Datei veraltet. Sie lebt in einem Repository, beschreibt Services anderer Leute, und niemand ist dafür zuständig.
- Sie weiß nichts über Health.
depends_onwartet auf einen Container, nicht auf einen antwortbereiten Service.
Dieselbe Umgebung, an beiden Orten
So endet eine docker-compose.yml eines kleinen Systems —zwei Services und
ihre Infrastruktur—, wenn jemand schon mit der Änderungsschleife gekämpft hat:
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 # bei jeder Änderung neu bauen
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'] # der zweite für den Debugger
depends_on:
postgres: { condition: service_healthy }
payments:
build: ../payments
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/payments
ports: ['8081:8081']
Es funktioniert. Was es kostet, steht nicht in der Datei, sondern drumherum: jede Änderung
an orders geht durch ein build; auf Port 5005 muss man sich
einigen, ihn mappen und in der IDE jeder einzelnen Person konfigurieren;
PAYMENTS_URL ist von Hand geschrieben, und payments auf die Cloud
zeigen zu lassen bedeutet, die Datei zu ändern (und daran zu denken, sie nicht zu
committen); und diese Datei lebt in einem Repository, das nicht das von
payments ist, also aktualisiert sie niemand, wenn payments eine
Variable ändert.
Das Gegenstück in Aseptic ist keine weitere Datei wie diese: es ist, dass die Services
nicht verpackt werden. orders und payments starten als Prozesse,
mit dem Hot Reload, den ihr Framework schon mitbringt, und dem Debugger angehängt wie an
jeden lokalen Prozess. Das Einzige, was in Docker bleibt, ist die Infrastruktur —Postgres
und Kafka—, die die App startet und deren Ports sie remappt, wenn sie belegt sind. Und die
URLs zwischen den Services werden nicht geschrieben: sie werden beim Start injiziert, je
nachdem, wohin du jede Abhängigkeit hast zeigen lassen.
orders ← lokaler Prozess, Port 8080
├── postgres → Infrastruktur in Docker (Aseptic startet sie)
├── kafka → Infrastruktur in Docker
└── payments → lokal | Cloud | Mock ← das ändert sich mit einem Klick
Die Änderung, auf die es ankommt, ist die letzte Zeile. In Compose heißt „heute will ich
payments gegen die Cloud-Umgebung“ YAML ändern; hier heißt es, das Ziel einer
Abhängigkeit zu ändern, und der Rest des Szenarios merkt es von selbst. Und nichts davon
wird in deinen Repositories abgelegt: das Szenario lebt außerhalb, es gibt also keine
Umgebungsdatei, die in einem Pull Request zu prüfen wäre.
Die Alternativen, ehrlich
| Werkzeug | Was es wirklich ist | Einstiegskosten |
|---|---|---|
| Tilt | Eine schnelle innere Schleife gegen Kubernetes, mit einer Oberfläche für Builds, Logs und Health | Ein Cluster, Images und ein Tiltfile pro Repo |
| Skaffold | Build, Push und Deploy nach Kubernetes in einem Befehl, mit Profilen | Ein Cluster, Images, Manifeste und eine skaffold.yaml |
| DevSpace | Dein Code, der in einem Entwicklungscontainer im Cluster läuft, mit Dateisynchronisation | Ein Cluster, und die Bereitschaft, auf der anderen Seite zu debuggen |
| Garden | Ein Abhängigkeitsgraph für Bauen, Deployen und Testen, geteilt von Entwicklung und CI | Eine Plattformentscheidung, und jemand, der den Graphen übernimmt |
| Telepresence | Ein lokaler Prozess, in einen echten Cluster gehängt, der dessen Verkehr abfängt | Ein gesunder gemeinsamer Cluster und Konnektivität dorthin |
| Lokales Kubernetes (kind, minikube) | Die echten Primitive auf deiner Maschine, damit das Getestete die Form der Produktion hat | Speicher, und der Deploy-Zyklus bei jeder Änderung |
| Aseptic | Services als native Prozesse, jede Abhängigkeit auf lokal, Cloud oder einen Mock gezeigt | Es installieren; Docker nur für die gemeinsame Infrastruktur |
Das Muster hinter der Liste
Fünf der sieben antworten auf „Compose reicht nicht“ mit „dann nimm Kubernetes lokal“. Das ist eine stimmige Antwort, und wenn du in Kubernetes deployst, kauft sie dir eine Ähnlichkeit, die dir nichts anderes gibt. Sie holt aber auch den Build- und Deploy-Zyklus des Clusters in die Schleife, die du zweihundertmal am Tag wiederholst.
Aseptic ist absichtlich das Schräge in der Liste: es setzt voraus, dass du keinen Cluster auf deiner Maschine willst, um einen Ablauf zu testen. Deine Services laufen als Prozesse, die gemeinsame Infrastruktur —Kafka, Redis, PostgreSQL— wird dir in Docker gestartet, und jede Abhängigkeit wird auf einen lokalen Service, eure gemeinsame Cloud-Umgebung oder einen Mock aufgelöst, mit beim Start umgeschriebenen URLs, um kein Repository anzufassen.
Wo Aseptic die falsche Wahl ist
Wenn du den Kubernetes-Teil testen musst —Ingress, Network Policies, Sidecars, Probes, Ressourcenlimits—, führt Aseptic nichts davon aus und nützt dir nichts. Wenn deine Services nur in einem vorbereiteten Namespace starten, ist sie außerhalb auszuführen keine Abkürzung: es ist eine Neuschreibung. Und wenn dir die tägliche Prüfung, dass deine Images und Manifeste noch funktionieren, mehr wert ist als eine schnelle Schleife, dann geben dir das Skaffold oder Tilt und Aseptic nicht.
Es ist außerdem in öffentlicher Beta, erscheint für Windows, macOS und Linux und ist nicht quelloffen. Alle anderen Werkzeuge dieser Liste sind Open Source, und für manche Teams entscheidet das schon alles.
Wie man ohne Tabellenkalkulation wählt
- Starten deine Services mit Umgebungsvariablen und einer Datenbank? Wenn ja, ist sie nativ auszuführen die billigste Schleife, die du haben kannst.
- Testest du deinen Code oder dein Deployment? Dein Code braucht keinen Cluster. Dein Deployment braucht nichts anderes.
- Passt das System auf eine Maschine? Wenn es wirklich nicht passt, ist Telepresence oder ein gemeinsamer Cluster die ehrliche Antwort.
- Wer pflegt die Konfiguration? Ein Werkzeug, dessen Konfiguration niemandem gehört, ist in zwei Quartalen verwaist, egal was du wählst.
Der breite Vergleich stellt Docker Compose, ein lokales Kubernetes und Aseptic ausführlicher nebeneinander.
Häufige Fragen
Was ist die Alternative zu Docker Compose für Microservices?
Das hängt davon ab, was dich gerade kostet. Ist es die Ähnlichkeit zur Produktion, ein lokales Kubernetes mit Tilt oder Skaffold; ist es die tägliche Schleife der Arbeit an mehreren Services, ein lokaler Orchestrator. Die Seite vergleicht die fünf Ansätze und wo jeder scheitert.
Greift Docker Compose für Microservices zu kurz?
Nicht für die Infrastruktur, das kann es am besten. Es greift zu kurz, wenn in der Compose-Datei deine Services stehen: für jede Änderung ein Image bauen, ohne bequemen Hot Reload, und mit der Kommunikation zwischen ihnen von Hand gelöst.
Gibt es eine Option ohne Kubernetes?
Ja: bei Compose bleiben, oder ein lokaler Orchestrator wie Aseptic, der Docker für die Infrastruktur nutzt und deine Services als Prozesse der Maschine ausführt.