Zurück zur Startseite

Blue-Green-Deployment auf Docker Compose ohne Ausfallzeit

Der Artikel beschreibt die Implementierung von Blue-Green-Deployment auf Docker Compose ohne Einsatz von Kubernetes. Er behandelt Aspekte der Verwaltung von Webdiensten und Hintergrundworkern, graceful shutdown, Kompatibilität bei Datenbankmigrationen und Automatisierung durch Deployment-Skripte.

Blue-Green-Deployment ohne Kubernetes: Praxis auf Docker Compose
Advertisement 728x90

# Blue-Green-Deployment ohne Kubernetes: Implementierung auf Docker Compose mit Null-Ausfallzeit

Die Implementierung eines Blue-Green-Deployments ist auch ohne Orchestratoren wie Kubernetes möglich – Docker Compose, nginx und eine durchdachte Graceful-Shutdown-Logik reichen aus. Dieser Ansatz ist besonders relevant für Teams, die auf dedizierten Servern oder virtuellen Maschinen arbeiten, wo der Einsatz eines vollständigen Clusters aus wirtschaftlichen oder architektonischen Gründen unpraktikabel ist. Der Artikel beschreibt die technische Umsetzung des Continuous Deployments für Web-Services und Background-Worker unter Berücksichtigung der Besonderheiten der Nachrichtenverarbeitung und des Status-Managements.

Blue-Green-Architektur auf Docker Compose

In der grundlegenden Konfiguration wird jede Anwendung dupliziert: Es gibt zwei unabhängige Instanzen – blue und green. Beide werden als separate Services in docker-compose.prod.yml gestartet, aber nur eine erhält zu jedem Zeitpunkt Traffic. Die Weiterleitung übernimmt ein Reverse-Proxy (nginx im Beispiel), der während des Deployments die Upstream-Adresse umschaltet. Grundprinzip: Die neue Instanz wird vollständig gestartet und besteht Health Checks, bevor die alte gestoppt wird.

Die Konfiguration erfordert die explizite Angabe von Ports für jede Instanz:

Google AdInline article slot
web-blue:
  ports:
    - "127.0.0.1:8002:8000"

web-green:
  ports:
    - "127.0.0.1:8003:8000"

Das ermöglicht nginx den Zugriff auf die gewünschte Instanz über localhost und einen spezifischen Port. Diese Einrichtung vermeidet Konflikte und vereinfacht das Lifecycle-Management.

Umgang mit Background-Workern

Background-Prozesse (Worker), die Nachrichten aus einer Queue konsumieren (z. B. RabbitMQ), erfordern einen speziellen Ansatz. Ein einfaches Stoppen des Containers führt zu Nachrichtenverlust oder erneuter Verarbeitung bei nicht-idempotenten Operationen. Die Lösung ist die Implementierung eines Graceful Shutdowns auf Anwendungsebene.

Dies wird über eine Singleton-Klasse mit einer is_accepting-Flag umgesetzt. Vor der Verarbeitung jeder Aufgabe prüft der Worker diese Flag:

Google AdInline article slot
  • Wenn is_accepting == True – wird die Aufgabe ausgeführt.
  • Wenn is_accepting == False – wird die Nachricht mit requeue=True zurück in die Queue gestellt.

Bei Erhalt des SIGTERM-Signals wird die Flag auf False gesetzt, woraufhin die Anwendung auf das Abschließen aller laufenden Aufgaben wartet (mit einem Puffer von 5–10 Sekunden) und dann herunterfährt. So gehen keine Nachrichten verloren und es entstehen keine Dateninkonsistenzen.

Wichtige Nuancen:

  • Bei Multi-Process-Workern (z. B. ProcessPoolExecutor) muss der is_accepting-Status für alle Child-Prozesse zugänglich sein. Andernfalls verarbeiten einige Consumer weiterhin neue Aufgaben.
  • Nicht-idempotente Operationen erfordern zusätzliche Schutzmaßnahmen: Erneute Verarbeitung kann die Datenintegrität zerstören.
  • Ein verteilter Flag (z. B. in Redis) verkompliziert die Architektur, kann aber in Systemen mit hoher Last gerechtfertigt sein.

Deployment-Skript: Schritt-für-Schritt-Logik

Das Deployment-Skript automatisiert den Wechsel zwischen den Instanzen. Die Logik ist für Web-Services und Worker gleich, aber mit unterschiedlichen Einstiegspunkten.

Google AdInline article slot

Hauptphasen:

  • Ermittlung der aktiven Instanz (durch Analyse der nginx-Konfiguration oder der Liste laufender Container).
  • Starten der inaktiven Instanz (docker compose up -d).
  • Überprüfung der Bereitschaft der neuen Instanz via Health Check (bis zu 30 Versuche mit 2-Sekunden-Intervallen).
  • Aktualisierung der nginx-Konfiguration und Ausführen von nginx -s reload.
  • Warten auf das Abschließen aller aktiven HTTP-Anfragen (meist 5 Sekunden).
  • Stoppen der alten Instanz (docker compose stop).

Beispiel für einen Web-Service:

echo "server 127.0.0.1:${INACTIVE_PORT};" > "$UPSTREAM_CONF"
nginx -t && nginx -s reload
sleep 5
$COMPOSE stop web-${ACTIVE}

Diese Abfolge stellt sicher, dass Traffic nie auf einen unvorbereiteten Service geleitet wird und die alte Instanz erst nach vollständigem Wechsel herunterfährt.

Kompatibilität von Datenbankschemata und Migrationen

Eine der größten Herausforderungen beim Blue-Green-Deployment ist der parallele Betrieb zweier Anwendungsversionen gegen dieselbe Datenbank. Um Fehler zu vermeiden, müssen alle Migrationen rückwärtskompatibel sein.

Empfohlener Ansatz – zweistufiges Update:

  • Erstes Deployment: Entfernen der Nutzung des veralteten Feldes/Tabellen im Code, aber Beibehalten der Struktur in der Datenbank. Beide Versionen – neu und alt – funktionieren korrekt.
  • Zweites Deployment (nach vollständigem Traffic-Wechsel): Durchführen der Migration zum Entfernen ungenutzter Schema-Elemente.

Das erhöht die Anzahl der Operationen, eliminiert aber das Risiko, dass die alte Instanz aufgrund von Schema-Inkompatibilitäten abstürzt.

Wichtige Punkte

  • Blue-Green-Deployment auf Docker Compose ist ohne Kubernetes möglich, erfordert aber manuelles Management von Instanzen und Proxy.
  • Graceful Shutdown für Worker ist entscheidend – ohne ihn können Nachrichten verloren gehen oder dupliziert werden.
  • Alle Datenbank-Migrationen müssen rückwärtskompatibel sein; Feldentfernungen erfordern einen zweistufigen Ansatz.
  • Health Check der neuen Instanz ist vor dem Traffic-Wechsel zwingend erforderlich.
  • Nginx-Konfiguration muss atomar aktualisiert und mit nginx -t validiert werden.

— Editorial Team

Advertisement 728x90

Weiterlesen