Docker Compose Beispiel für Redundanz Failover mit Traefik
Im folgenden Beispiel wird gezeigt, wie Traefik in Docker Compose konfiguriert werden kann. Dabei kann vollständig auf separate Konfigurationsdateien verzichtet werden. Die benötigten Konfigurationen werden als Befehlsparameter übergeben oder über Labels festgelegt.
Die Dateien, die als Projekt verwendet werden, befinden sich auf der Seite HTTP(S)-Failover-Konzepte für REST, OPC UA Server & Web-Management im OPC Router.
Wie beim Nginx-Beispiel betrifft auch diese Konfiguration nur das externe Failover für die Server-Endpunkte. Die eigentliche Redundanz des OPC Router-Paares wird unabhängig davon im OPC Router konfiguriert.
Beide OPC Router-Container tragen bewusst dieselben Router- und Middleware-Labels. Sie konkurrieren dadurch nicht miteinander: Traefik fasst gleichnamige Labels zu einem Dienst (opcrouter-service) mit zwei Servern zusammen. Welcher der beiden eine Anfrage erhält, entscheidet der Health Check – er fragt den unter healthcheck.path angegebenen Pfad ab und nimmt den Container, der nicht antwortet, aus der Verteilung. Genau das ist das Failover.
Die Traefik-Option --api.insecure=true dient in diesem Beispiel nur dazu, das Dashboard für Test- und Einrichtungszwecke einfach erreichbar zu machen. In produktiven Umgebungen sollte das Dashboard nicht ungeschützt veröffentlicht, sondern abgesichert oder deaktiviert werden.
Passwort und Pre-Shared-Key stehen hier als Platzhalter. Tragen Sie diese Werte nicht im Klartext in eine Compose-Datei ein, die in einer Versionsverwaltung landet – sie gelten für beide Instanzen und sind der Schlüssel zur Redundanzverbindung. Verwenden Sie stattdessen den Secrets-Store des OPC Routers. Den Pre-Shared-Key erzeugen Sie über die Schaltfläche „Generieren“ im Bereich Pre-Shared-Key, siehe Sichere Redundanz.
services:
traefik:
image: traefik:v3.0
restart: always
networks:
- opcrouter-net
# Konfigurationen als Befehlsparameter
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--entrypoints.web.address=:80"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--ping"
ports:
- "5080:80"
- "5081:8080" # Traefik Dashboard (optional)
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
opcrouter-primary:
image: opcrouter/runtime:latest
restart: always
networks:
- opcrouter-net
ports:
- "5085:8080"
environment:
- OR_I_ACCEPT_EULA=true
- INITIAL_USERNAME=admin
- INITIAL_PASSWORD=<your-password>
- OR_REDUNDANCY_MODE=primary
- OR_REDUNDANCY_LOCAL_MANAGEMENT_ADDRESS=http://opcrouter-primary:8080
- OR_REDUNDANCY_SHARED_KEY=<your-pre-shared-key>
- OR_IMPORT_SOURCE=/inray/REST_Primary.rpe
volumes:
# Projekt im Container verfügbar machen
- ../REST_Primary.rpe:/inray/REST_Primary.rpe
# Konfigurationen über Labels
labels:
- "traefik.enable=true"
# Reagiert auf den Präfix /api
- "traefik.http.routers.api-router.rule=PathPrefix(`/api`)"
- "traefik.http.routers.api-router.entrypoints=web"
- "traefik.http.routers.api-router.service=opcrouter-service"
- "traefik.http.routers.api-router.middlewares=api-rewrite"
# Ersetzt /api/ durch /services/MyRestServer/api/
- "traefik.http.middlewares.api-rewrite.replacepathregex.regex=^/api/(.*)"
- "traefik.http.middlewares.api-rewrite.replacepathregex.replacement=/services/MyRestServer/api/$$1"
# Load Balancing Konfiguration
- "traefik.http.services.opcrouter-service.loadbalancer.server.port=8080"
# Verfügbarkeit durch Anfragen an angegebenen Pfad prüfen
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.path=/health/runtime/ready"
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.interval=5s"
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.timeout=2s"
opcrouter-secondary:
image: opcrouter/runtime:latest
restart: always
networks:
- opcrouter-net
ports:
- "5086:8080"
environment:
- OR_I_ACCEPT_EULA=true
- INITIAL_USERNAME=admin
- INITIAL_PASSWORD=<your-password>
- OR_REDUNDANCY_MODE=secondary
- OR_REDUNDANCY_SHARED_KEY=<your-pre-shared-key>
- OR_REDUNDANCY_ADDRESS=http://opcrouter-primary:8080
- OR_REDUNDANCY_LOCAL_MANAGEMENT_ADDRESS=http://opcrouter-secondary:8080
- OR_REDUNDANCY_PRIMARY_TIMEOUT=30
- OR_REDUNDANCY_SECONDARY_HEARTBEAT_INTERVAL=10
- OR_IMPORT_SOURCE=/inray/REST_Secondary.rpe
volumes:
# Projekt im Container verfügbar machen
- ../REST_Secondary.rpe:/inray/REST_Secondary.rpe
# Konfigurationen über Labels
labels:
- "traefik.enable=true"
# Reagiert auf den Präfix /api
- "traefik.http.routers.api-router.rule=PathPrefix(`/api`)"
- "traefik.http.routers.api-router.entrypoints=web"
- "traefik.http.routers.api-router.service=opcrouter-service"
- "traefik.http.routers.api-router.middlewares=api-rewrite"
# Ersetzt /api/ durch /services/MyRestServer/api/
- "traefik.http.middlewares.api-rewrite.replacepathregex.regex=^/api/(.*)"
- "traefik.http.middlewares.api-rewrite.replacepathregex.replacement=/services/MyRestServer/api/$$1"
# Load Balancing Konfiguration
- "traefik.http.services.opcrouter-service.loadbalancer.server.port=8080"
# Verfügbarkeit durch Anfragen an angegebenen Pfad prüfen
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.path=/health/runtime/ready"
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.interval=5s"
- "traefik.http.services.opcrouter-service.loadbalancer.healthcheck.timeout=2s"
networks:
opcrouter-net: