Traefik - ein Reverse-Proxy für Docker

Durch Docker können wir schnell und einfach unsere Services bzw. Microservices verwalten, konfigurieren und auf einem oder mehreren Hosts laufen lassen. Doch kann das Management der Ports und der entsprechenden Freigaben pro Applikation schnell unübersichtlich werden. So wollen eventuell mehrere Webapps über den Port 80 mit dem Anwender reden. Da dies ja nur eine Anwendung auf einer Maschine tun kann, müssen andere Ports benutzt werden und der Endanwender muss dies beim Aufruf der URL beachten. Zusätzlich müssen die DNS-Einträge für die Services direkt auf den Host verweisen, der die Container hostet. Dies führt dazu, dass die Infrastruktur exponiert wird.

Typischerweise wird dafür in klassischen Szenarien ein Reverse-Proxy (https://de.m.wikipedia.org/wiki/Reverse_Proxy) eingesetzt. Dieser versteckt die eigene Infrastruktur vor direkten Zugriffen aus dem Internet und übernimmt mehrere Aufgaben auf einmal. Neben der Weiterleitung auf die richtigen Hosts und Ports (in unserem Fall Container) beherrschen diese Tools auch Features wie SSL, Authentifizierung, Lastverteilung und Caching.

image-6.png

Hier soll der Reverse-Proxy Traefik(https://traefik.io) vorgestellt und seine Verwendung gezeigt werden. Er ist für uns zu einem wichtigen Werkzeug in unserer Infrastruktur geworden, da der Proxy leichtgewichtig daherkommt und einfach zu konfigurieren ist. Traefik ist als Docker-Container verfügbar. (https://hub.docker.com/_/traefik/)

Konfiguration des Traefik-Containers

Das Beispiel soll zeigen, wie man Traefik aufsetzt und auf dem gleichen Host-Rechner einen Service startet und diesen über den Proxy anspricht. Außerdem soll die Traefik-Web-UI gestartet werden.

In unserem Beispiel werden wir docker-compose verwenden. (https://docs.docker.com/compose/) Die docker-compose.yml für Traefik sieht folgendermaßen aus:

docker-compose.yml:

version: '3.5'

services:

  traefik:
    restart: always
    image: traefik:1.6
    container_name: traefik
    ports:
      - "80:80"
      - "8080:8080"
    networks:
      - web
    volumes:
      - ./traefik.toml:/etc/traefik/traefik.toml
      - /var/run/docker.sock:/var/run/docker.sock:ro

networks:
  web:
    external: true

In der Container-Konfiguration sieht man, dass der Name des Containers "traefik" sein wird. Außerdem sind die Ports 80 für den HTTP-Zugriff auf die Services-Container und der Port 8080 für die Traefik-Web-UI aus dem Traefik-Container auf die gleichen Ports des Host.-Systems weitergeleitet. Weiterhin ist die Traefik-Konfigurationsdatei traefik.toml (siehe unten) in den Container eingebunden.
Damit Traefik automatisch zur Laufzeit neue Container erkennt und den Traffic zu ihnen weiterleiten kann, muss der Docker-Socket dem Traefik-Container bereitgestellt werden.

Bevor der Container gestartet werden kann, muss außerdem das Docker-Netzwerk "web" angelegt worden sein. Es ist hier in der Container-Konfiguration als extern angelegtes Netzwerk angegeben und der Traefik-Container wird sich nur in diesem befinden. Dies dient der Isiolation, so dass bspw. Datenbank-Container von Diensten sich nicht im selben Netzwerk wie der Proxy befinden und somit unsichtbar bleiben können. Die Anlage des Docker-Netzwerks geht einfach über den Befehl:

docker network create web

Die Konfiguration wird in der Datei traefik.toml vorgenommen und muss in unserem Beispiel im selben Ordner wie die Datei docker-compose.yml liegen.

traefik-toml:

[entryPoints]
    [entryPoints.http]
    address = ":80"

[api]

[docker]

Viele der hier gezeigten Einstellungen lassen sich entweder zentral am Proxy einstellen oder können im Container-Setup des Services festgelegt werden. Details dazu findet man unter https://docs.traefik.io/configuration/backends/docker/

Zum Start des Traefik-Containers einfach “docker-compose up -d” in dem Ordner aufrufen, in dem sich die docker-compose.yml und traefik.toml befinden.

Wenn man nun im Browser seiner Wahl “localhost:8080” aufruft, so bekommt man die Traefik-Web-UI zu sehen:

image-7.png

Traefik unterscheidet zwischen Backends, was die Container mit den entsprechenden Services sind, und Frontends, welche Protkoll (http,https) und Routingregeln (Subdomain oder Kontextpfad) darstellen. Noch ist nicht viel los, da wir noch keinen weiteren Service auf diesem Host gestartet haben. Doch das folgt sofort.

Traefik als Proxy für einen Service einsetzen

Ein neuer Service wird beim Containerstart standardmäßig von Traefik automatisch erkannt. Um den Container nun durch den Proxy sichtbar zu machen fügen wir zu der Container-Konfiguration ein Label "traefik.frontend.rule=Host:myservice.localhost" hinzu. Dieses sorgt dafür , dass unter der Subdomain "myservice" auf "localhost" unser Container antwortet. In diesem Beispiel werden wir einen Tomcat-Container laufen lassen. Der Tomcat-Server läuft intern auf dem Port 8080, welchen er nur über das interne Docker-Netzwerk veröffentlicht. Traefik wird den automatisch von Port 80 extern auf Port 8080 in dem Container routen.

docker-compose.yml:

version: '3.5'
services:
  myservice:
    restart: always
    image: tomcat:latest
    container_name: tomcat
    expose:
      - "8080"
    labels:
      - "traefik.frontend.rule=Host:myservice.localhost"
    networks:
      - web

networks:
  web:
    external: true

Wenn der Container gestartet wurde kann man mit folgendem Befehl den Code der Default-Tomcat-Seite sehen:

curl -H Host:myservice.localhost http://127.0.0.1

Alternativ kann man auch die eigentlich nicht korrekte Subdomain in /etc/hosts eintragen:

/etc/hosts:

…
127.0.0.1   localhost
127.0.0.1   myservice.localhost
…

Danach kann man im Browser die URL "myservice.localhost" aufrufen und kommt zur Tomcat-Startseite:

image-8.png

Eigene Domain & Subdomains

Nun soll Traefik natürlich nicht den Verkehr von "localhost" managen, sondern den Verkehr der Subdomains von unserer Hauptdomain zu den richten Containern leiten. Dazu muss die traefik.toml um folgenden Eintrag unter dem Punkt "[docker]" ergänzt werden:

traefik.toml:

…
[docker]
…
domain = "code-fabrik.com"
…

Anschließend muss der Traefik-Container neu gestartet werden:

docker-compose restart

Zusätzlich müssen wir noch die Container-Konfiguration des Services anpassen:

docker-compose.yml:

…
labels:
      - "traefik.frontend.rule=Host:myservice.code-fabrik.com"
…

Wenn die DNS-Konfiguration für die Domain "code-fabrik.com" bzw. der Subdomain "myservice.code-fabrik.com" korrekt eingestellt wurden, leitet Traefik nun die Anfragen korrekt zum Tomcat-Container weiter.

Fazit

Mit Traefik kann man in kürzester Zeit mehrere Services auf einem Host hinter einem Proxy laufen lassen. Das Werkzeug verrichtet dabei mit wenig Bedarf an Arbeitsspeicher und CPU zuverlässig seinen Dienst. Zukünftige Artikel sollen zeigen, wie man mit Traefik SSL über Let’s Encypt (https://letsencrypt.org) aktiviert, wie man für Container eine Authentifizierung einstellt oder wie IP-Whitelisting eingerichtet wird.