Alle Docker-Projekteparallel auf einem Rechner
Drei Projekte, ein Rechner, ständig derselbe Konflikt
Wer mehrere Anwendungen parallel betreut, verbringt einen Teil des Tages mit Infrastruktur statt mit dem Produkt.
Jedes Projekt bringt seine eigene docker-compose.yml mit, und jede davon will Port 80, 3306 oder 8080 für sich. Sobald das zweite Projekt startet, meldet Docker address already in use. Die übliche Antwort: im Projekt die Ports umbiegen, also 8081 statt 8080, 3307 statt 3306. Damit liegt eine lokale Anpassung in einer Datei, die dem Projekt gehört und im Repository versioniert ist.
Was bleibt, sind Adressen, die niemand im Kopf behält. Der Shop läuft auf localhost:8080, die API auf localhost:8081, das Frontend auf localhost:3000. Weil alles auf demselben Host liegt, teilen sich die Anwendungen den Cookie-Namensraum, und Anfragen zwischen zwei Ports gelten als Cross-Origin. Fehler, die es in Produktion nicht gibt, entstehen so nur lokal.
Der übliche Ausweg ist Reihenbetrieb: erst das eine Projekt herunterfahren, dann das andere starten. Bei zwei Kontextwechseln am Tag kostet das mehr Zeit als die Aufgabe selbst.
Was MultiDocker daran ändert
Routing über Hostnamen statt über Ports
Der zentrale Traefik v3 nimmt jede Anfrage an und entscheidet anhand des Hostnamens, welches Projekt antwortet.
# Einmalig: Zertifikat, DNS-Resolver und Edge-Stack
mdocker setup
# Drei Projekte registrieren und starten
mdocker init ~/Projects/shop
mdocker init ~/Projects/api
mdocker init ~/Projects/cms
mdocker up shop api cms
# Alle drei sind jetzt parallel erreichbar
# https://shop.coding9.test
# https://api.coding9.test
# https://cms.coding9.test
# https://mail.coding9.test (Mailcatcher)
mdocker ls # Status aller Projekte
mdocker doctor # Werkzeuge, Ports, DNS und Zertifikat prüfenDie Compose-Datei bleibt unberührt
MultiDocker schreibt pro Projekt eine Override-Datei in das eigene Konfigurationsverzeichnis und ruft docker compose mit beiden Dateien auf. Der Override entfernt die Host-Port-Mappings, hängt die Container an das gemeinsame Edge-Netz und setzt die Traefik-Labels für den Hostnamen. Im Repository ändert sich nichts, und wer ohne MultiDocker arbeitet, startet das Projekt weiter wie bisher.
HTTPS wie auf dem Server
Beim Setup legt MultiDocker über mkcert ein Wildcard-Zertifikat für die Testdomain an und trägt einen lokalen DNS-Resolver ein. Danach löst jeder Name unterhalb der Domain auf den eigenen Rechner auf und der Browser akzeptiert das Zertifikat. Secure-Cookies, SameSite-Regeln und OAuth-Redirects lassen sich damit lokal so testen, wie sie später laufen.
CLI, App und ein gemeinsamer Edge-Stack
Alle Bausteine greifen auf dieselbe Registry und dieselben Overrides zu - Terminal und App zeigen denselben Stand.
mdocker-CLI
macOS-App
Traefik-Edge
Mailcatcher zentral
Profil-Erkennung
DB-Toolkit
Demo-Link teilen
Override statt Fork
Vom geklonten Repository zur HTTPS-Adresse
Setup einmalig
mdocker setup legt Wildcard-Zertifikat, DNS-Resolver, Edge-Netz und den Traefik-Stack an.
Projekt registrieren
mdocker init zeigt auf den Projektordner, erkennt das Profil und erzeugt die Override-Datei.
Starten
mdocker up ruft docker compose mit Original- und Override-Datei auf - ohne Host-Ports.
Im Browser öffnen
Das Projekt antwortet unter seinem eigenen Hostnamen, zum Beispiel https://shop.coding9.test.
Weniger Infrastruktur, mehr Projektzeit
Gebaut für Teams, die mehrere Anwendungen gleichzeitig betreuen
MultiDocker ist in unserer eigenen Entwicklung entstanden und läuft dort täglich. Warum wir es gebaut haben und welche Wege wir dabei verworfen haben, steht im Beitrag zur Entstehung von MultiDocker.
MultiDocker im Detail
Was ist MultiDocker?
MultiDocker ist ein Werkzeug für lokale Entwicklungsumgebungen auf macOS. Es lässt beliebig viele docker-compose-Projekte nebeneinander laufen und macht jedes davon unter einem eigenen HTTPS-Hostnamen erreichbar, zum Beispiel shop.coding9.test und api.coding9.test. Statt Ports zu verteilen, routet ein zentraler Traefik den Verkehr anhand des Hostnamens an den passenden Container.
Muss ich meine docker-compose.yml dafür anpassen?
Nein. MultiDocker legt pro Projekt eine eigene Override-Datei außerhalb des Repositories an und startet docker compose mit beiden Dateien. Die Override-Datei entfernt die Host-Port-Mappings, hängt die Container an das gemeinsame Edge-Netz und setzt die Traefik-Labels. Die Datei im Projekt bleibt unverändert und lässt sich weiter ohne MultiDocker verwenden.
Warum HTTPS statt localhost?
Cookies mit Secure-Flag, SameSite-Regeln, CORS-Header, OAuth-Redirects und Service Worker verhalten sich unter einem echten Hostnamen mit gültigem Zertifikat anders als unter localhost mit wechselnden Ports. MultiDocker legt beim Setup ein Wildcard-Zertifikat über mkcert an und trägt einen lokalen DNS-Resolver für die Testdomain ein, sodass lokal dieselbe Konstellation gilt wie später auf dem Server.
Welche Docker-Umgebung wird vorausgesetzt?
MultiDocker läuft auf macOS mit Docker Desktop oder OrbStack. Zusätzlich werden mkcert, yq, jq und openssl benötigt - der Befehl mdocker doctor prüft alle Abhängigkeiten und meldet, was fehlt oder welcher Prozess Port 80 beziehungsweise 443 belegt.
Wie komme ich vom Host an die Datenbanken?
Über mdocker inspect. Der Befehl listet je Service den Container, die internen Ports und einen fertigen Connection-String für MySQL, PostgreSQL oder Redis zum Kopieren in den Datenbank-Client. Für Dumps, Snapshots und das Zurückspielen gibt es mdocker db mit den Verben dump, snapshot, snapshots, restore und restore-snapshot.
Kann ich einem Kunden einen laufenden Stand zeigen?
Ja, über mdocker share. Der Befehl öffnet einen Cloudflare-Quick-Tunnel auf das lokal laufende Projekt und gibt eine öffentliche HTTPS-Adresse aus. Die Adresse wechselt bei jedem Start und ist ohne Passwortschutz erreichbar - für eine kurze Abstimmung genügt das, für Dauerbetrieb ist eine echte Staging-Umgebung die richtige Wahl.
Lokale Umgebung, die nicht im Weg steht
Sehen Sie sich MultiDocker im Detail an oder sprechen Sie mit uns über Ihre lokale Entwicklungsumgebung - vom Compose-Setup bis zur Übergabe an neue Teammitglieder.