Traefik v3 mit Docker Compose — Reverse Proxy in 10 Minuten

Traefik v3 mit Docker Compose — Reverse Proxy in 10 Minuten

Du willst deine Self-Hosted-Dienste sauber unter einer Domain erreichbar machen, mit automatischen SSL-Zertifikaten? Traefik macht genau das — und mit Docker Compose hast du das Ganze in unter 10 Minuten am Laufen.

Was ist Traefik?

Traefik ist ein Open-Source Reverse Proxy, der speziell für Container-Umgebungen gebaut wurde. Statt wie bei Nginx jede Route manuell zu konfigurieren, erkennt Traefik deine Docker-Container automatisch über Labels. Neuer Container mit passendem Label hochgefahren → Traefik routet sofort den Traffic dahin. Kein Reload, kein Neustart.

Voraussetzungen

Du brauchst einen Linux-Server (VPS oder Homelab), Docker und Docker Compose installiert, eine Domain die auf deinen Server zeigt, und Port 80 + 443 offen in der Firewall. Das wars.

Projekt-Struktur

Ich arbeite mit einem eigenen Docker-Netzwerk für Traefik. Alle Container die von außen erreichbar sein sollen, hängen sich an dieses Netzwerk. So bleibt alles sauber getrennt.

mkdir -p ~/traefik && cd ~/traefik
touch docker-compose.yml
touch acme.json && chmod 600 acme.json
docker network create proxy

Die acme.json speichert deine Let’s Encrypt Zertifikate. Die 600er Berechtigung ist Pflicht — Traefik weigert sich zu starten wenn die Datei für andere lesbar ist.

Die docker-compose.yml

services:
  traefik:
    image: traefik:v3.2
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/acme.json
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=proxy"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--certificatesresolvers.letsencrypt.acme.email=deine@mail.de"
      - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.deinedomain.de`)"
      - "traefik.http.routers.dashboard.service=api@internal"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.middlewares=auth"
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz$$hashedpassword"
    networks:
      - proxy

networks:
  proxy:
    external: true

Was passiert hier?

providers.docker.exposedbydefault=false bedeutet: Kein Container wird automatisch veröffentlicht. Nur wenn du explizit traefik.enable=true als Label setzt. Das ist ein wichtiger Security-Default — du willst nicht aus Versehen deinen Datenbankcontainer ins Internet stellen.

Der HTTP → HTTPS Redirect läuft über die Entrypoint-Redirection. Jeder Request auf Port 80 wird automatisch auf 443 umgeleitet. Let’s Encrypt holt sich die Zertifikate über die HTTP Challenge.

Ersten Service anbinden

Nehmen wir Uptime Kuma als Beispiel — ein Self-Hosted Monitoring Tool. In einer separaten docker-compose.yml:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.uptime.rule=Host(`status.deinedomain.de`)"
      - "traefik.http.routers.uptime.tls.certresolver=letsencrypt"
    networks:
      - proxy

networks:
  proxy:
    external: true

Drei Labels reichen: traefik.enable=true macht den Container sichtbar, die Router-Rule definiert die Domain, und der TLS-Certresolver kümmert sich um HTTPS. Kein Nginx-Config-Editieren, kein certbot renew Cronjob. Einfach docker compose up -d und es läuft.

Dashboard absichern

Das Traefik Dashboard zeigt dir alle Routen, Services und Middlewares auf einen Blick. Ist praktisch zum Debuggen, aber du willst es nicht offen im Netz stehen lassen. Die Basic Auth Middleware in der Compose-Datei sichert das ab. Den Hash für dein Passwort generierst du so:

sudo apt install apache2-utils
echo $(htpasswd -nb admin deinpasswort) | sed -e s/\$/\$\$/g

Den Output packst du in die basicauth.users Middleware. Für Produktivbetrieb empfehle ich statt Basic Auth eher eine Lösung wie Authelia oder Authentik — dazu kommt noch ein eigener Beitrag.

Troubleshooting

Die häufigsten Fehler bei Traefik-Setups: Container antwortet nicht? Check ob er im proxy Netzwerk ist. 404 statt deiner App? Prüf die Host-Rule — Tippfehler in der Domain. SSL-Fehler? Die acme.json muss chmod 600 haben und du brauchst einen gültigen DNS-Eintrag der auf deinen Server zeigt.

Traefik-Logs helfen weiter: docker logs traefik -f zeigt dir in Echtzeit was passiert.

Wie gehts weiter?

Du hast jetzt einen funktionierenden Reverse Proxy mit automatischem HTTPS. Als nächste Schritte empfehle ich: Rate Limiting und Security Headers als Traefik Middleware, CrowdSec als Intrusion Prevention vor Traefik, und ein Monitoring-Stack mit Prometheus + Grafana hinter Traefik. Das sind alles Themen die hier auf dem Blog noch kommen werden.

Den kompletten Code findest du wie immer auf GitHub. Fragen? Ab damit in die Kommentare oder über die Kontaktseite.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert