Traefik als Reverse Proxy mit Docker - Labels statt Konfigurationsdateien

Traefik als Reverse Proxy mit Docker - Labels statt Konfigurationsdateien

Traefik erkennt Docker-Container automatisch über Labels und konfiguriert sich selbst — kein Nginx-Reload, keine statischen Configs.

Wie Traefik mit Docker funktioniert

Traefik hört auf den Docker-Socket und liest Labels von laufenden Containern. Wenn ein Container mit dem richtigen Label startet, wird er automatisch als Backend registriert. Stoppt er, wird er entfernt. Alles ohne manuelle Konfiguration.

Traefik-Container einrichten

services:
  traefik:
    image: traefik:v3.0
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"   # Container müssen sich explizit anmelden
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.entrypoints=websecure"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"

volumes:
  letsencrypt:

exposedbydefault=false ist wichtig: Ohne dieses Flag würde Traefik jeden Container exponieren — das ist ein Sicherheitsrisiko.

App-Container mit Labels konfigurieren

services:
  app:
    image: myapp
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
      - "traefik.http.routers.myapp.entrypoints=websecure"
      - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
      - "traefik.http.services.myapp.loadbalancer.server.port=3000"
    networks:
      - traefik-public
      - internal

  db:
    image: postgres:16
    # Kein traefik.enable — nicht exponiert
    networks:
      - internal

networks:
  traefik-public:
    external: true   # Vom Traefik-Stack erstellt
  internal:

Das Label loadbalancer.server.port teilt Traefik mit, auf welchem Port die App intern lauscht — auch wenn der Container keinen ports:-Block hat.

HTTP zu HTTPS umleiten

labels:
  - "traefik.http.routers.myapp-http.rule=Host(`app.example.com`)"
  - "traefik.http.routers.myapp-http.entrypoints=web"
  - "traefik.http.routers.myapp-http.middlewares=redirect-https"
  - "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
  - "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"

Middleware: Authentifizierung

Traefik unterstützt BasicAuth direkt über Labels:

# Passwort-Hash generieren
echo $(htpasswd -nb admin secretpassword)
# Ausgabe: admin:$apr1$...
labels:
  - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$..."   # $$ escapt das $
  - "traefik.http.routers.myapp.middlewares=auth"

Traefik-Dashboard

Das Dashboard unter traefik.example.com (oder lokal auf Port 8080 mit --api.insecure=true) zeigt alle erkannten Routers, Services und Middlewares in Echtzeit — nützlich zur Fehlersuche.

# Lokal ohne TLS zum Testen
docker run traefik --api.insecure=true --providers.docker -p 80:80 -p 8080:8080 \
  -v /var/run/docker.sock:/var/run/docker.sock

Gemeinsames Netzwerk zwischen Stacks

Für mehrere Compose-Stacks auf einem Host:

docker network create traefik-public

Jeder Stack referenziert dieses Netzwerk als external: true. Traefik muss im selben Netzwerk sein wie die Ziel-Container — sonst kann er sie nicht erreichen.

Traefik ist besonders stark, wenn viele Dienste dynamisch kommen und gehen. Für statische Setups mit wenigen Diensten ist Nginx manchmal einfacher.