Traefik
Updates
01.01.2026 – Übertrag von adminwerk.systems 16.05.2023 – IPv6 Beispiel korrigiert 22.05.2023 – Verbesserung der Textqualität; Erklärungen zur traefik Konfiguration 26.06.2023 – IPv6 erneut korrigiert
Vorwort
Viele Jahre arbeite ich schon an und mit Root-Servern und habe auch immer meine eigenen Maschinen am Laufen. Die Setups und Installationen haben dabei immer auch ein hohes Maß an Aufwand erzeugt, natürlich auch ein hohes Maß an Spaß und Freude. Häufig war der Grund etwas Neues zu probieren oder zu evaluieren. Eine neue Version, ein neues Tool, eine neue eigene Cloud usw.
Jetzt gibt es ja schon einige Zeit ein Tool, das Abhilfe schaffen kann: docker. Mit docker konnte ich mich aber laaaange Zeit einfach nicht anfreunden. Vom monolithischen Server, zur Serverfarm mit Cluster, zur Virtualisierung, zu Containern?
„Aber Container … Was soll der Mist? Alte Kamellen in neuen Kleidern?“
Auszug aus dem Vorwort von „Skalierbare Container-Infrastrukturen“ von Oliver Liebel
Mit ausreichend Distanz und ausreichend Zeit (hüstel) habe ich mich mittlerweile mit docker angefreundet, Informationen gesucht, nachgebaut, erweitert, ergänzt und Freundschaft geschlossen.
Ziel
Das Ziel dieser Anleitung ist die Bereitstellung eines docker Servers. D.h. ich installiere auf einem root-Server docker und docker compose. Um die Ressourcen hier entsprechend sinnvoll zu nutzen (Auslastung des Severs), stellt dieser Server dann entsprechende weitere Web-Applikationen zur Verfügung. Auf der Ziellinie kann WordPress, Redmine, Bitwarden, … installiert und betrieben werden. Es bedarf keiner aufwendigen Konfigurationen und dem Handling verschiedener Konfigurationstypen. Wenn wir uns eingespielt haben, kommt (fast) alles im gleichen Format: YML.
Server vorbereiten
Die Basis für diesen und die viele andere Artikel ist ein Root-Server. Ob dieser Bare Metal oder Virtual ist, spielt dabei keine Rolle. Meine Basis ist ein CPX21 bei HETZNER . Damit habe ich die komplette Spielwiese für unter 10 EUR in einem DSGVO-konformen RZ (bei Auswahl der entsprechenden Location). Auf dem Server läuft Ubuntu 22.04 Minimal. Schaut dass hier die aktuellste LTS läuft, 22, 24 .., Support muss es haben.
Um immer auf dem aktuellen Stand zu bleiben source ich docker aus den offiziellen Repository, womit docker immer auf dem aktuellen Stand gehalten werden kann. Hast Du im Nachbau dieser Anleitung Ubuntu neu installiert, sind die nachfolgenden beiden Zeilen nicht zwingend notwendig, da nichts davon installiert sein sollte.
sudo apt remove docker docker-engine docker.io containerd runc
sudo rm /etc/apt/sources.list/docker.list
Im nächsten Schritt aktualisiere ich die Paketliste und installiere den ersten Schwung notwendiger Pakete. Das Sourcen der docker Repositories (PGP-Keys installieren etc) teilt mir diesen Prozess in mehrere Schritte.
Notwendige Pakete installieren
sudo apt update && sudo apt install apt-transport-https ca-certificates curl \
software-properties-common gnupg lsb-release apache2-utils
Offizielle Docker GPG Keys einbinden
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor \
-o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpgp
Repository einbinden
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
docker + docker compose
Schlussendlich installiere ich die neueste Docker Engine und Docker Compose ins System
sudo apt update && sudo apt install docker-ce docker-ce-cli \
containerd.io docker-buildx-plugin docker-compose-plugin
docker in Bootprozess einbinden
In wenigen Ausnahmefällen wird man den Schritt weglassen. Aber nach einem reboot sollte schon alles wieder mit starten. Das erledige ich durch nachfolgende Eingabe an der Shell
sudo systemctl enable docker.service && sudo systemctl enable containerd.service
Auf der docker-docs Homepage
wird beschrieben, wie die Installation mit hello-world getestet werden kann. Schlecht ist das nicht, denn damit siehst Du recht schnell ob erstmal die Laufzeitumgebung passt. Ich erspare mir das aber und fahre stattdessen gleich mit dem Reverse-Proxy traefik fort. Weiterführende Informationen findet man im Internet, z.B. die Anleitung auf digitalocean. [Q]
Nacharbeiten
Um auch zielgerichtet in die Zukunft zu blicken, aktivieren wir IPv6 für docker [Q]. Wer Du dich für einen Server bei Hetzner entschieden hast, dann solltest Du dich gleich in die Console einloggen. Hier steht die IPv6, die wir direkt brauchen werden. Mit vi /etc/docker/daemon.yml legen wir die entsprechende Datei an und befüllen diese mit Inhalt.
IPv6
{
"ipv6": true,
"fixed-cidr-v6": "2a01:4f9::::1/64"
}
Bei fixed-cidr-v6 muss die verwendete IPv6 rein, logisch.
Ein kleiner Hinweis. Die letzte Direktive schließt nicht mit einem Komma ab. Wenn Du also nachfolgend beschriebenes Live Restore nutzen möchtest, dann nach der fixed-cidr-v6 Direktive ein Komma ergänzen und nach der live-restore Direktive weglassen.
Live Restore
Live Restore ist auch eine nette Nacharbeit. Dabei bleiben die Container am Start, auch wenn der Daemon herunterfährt, z.B. bei einem Update. Auch dieser Eintrag ergänzt die JSON in der /etc/docker/daemon.yml.
{
"ipv6": true,
"fixed-cidr-v6": "2a01:4f9::::1/64",
"live-restore": true
}
traefik installieren
Einführung
Traefik
ist angetreten Netzwerk-Komplexität abzubauen. In ganz kurzer Zeit hat traefik arrivierten Systemen den Rang abgelaufen. Insbesondere unter dem Aspekt im Umfeld von Microservices verrichtet der Reverse Proxy und/oder Load Balancer herausragende Dienste.

Das Prinzip: traefik
Oh mein Gott – Theoretiker schlagen wieder zu!
Einfach gesagt greift Traefik den zielgerichteten Datenverkehr aus dem Internet, via https ab und leitet diesen dann an den eigentlichen Service weiter.
Was sind die Vorteile?
Traefik ist mit allen Cluster Technologien kompatibel (zB Kubernetes, Docker, Docker Swarm, AWS, …). Der Hamster braucht dabei keine spezielle Konfiguration sondern macht dies automatisch. In der Verbindung mit docker, was ja hier Thema ist, schreibt man also eine docker-compose.yml und die Dienste verbinden sich. Die Entwickler geben hier eine ausführliche Einführung
. Entscheidend, und damit macht es dann auch Spass, ist, dass traefik sich automatisch um die Zertifikate kümmert. Durch die entsprechenden Label in besagter docker-compose.yml werden die Zertifikate mit dem Hochfahren des Containers eingebunden.
Arbeitsverzeichnis(se)
Alle Container, die auf dem Server installiert werden, gefinden sich in /opt/containers. In einem eigenen Unterverzeichnis. Diesem Schema werden auch potentiell weiteren Anleitungen und Artikel folgen. Entsprechend kommt traefikin den Ordner /opt/containers/traefik/. Hier vorbereitet mit dem zugehörigen Volume für die Konfigurationen.
mkdir -p /opt/containers/traefik/data
SSL/TLS mit Certbot
Stand der Dinge, der Technik und des guten Geschmacks ist die Absicherung jeglicher Dienste mit SSL/TLS. Ergo wird im nächsten Schritt die Zertifikatsspeicher-Datei acme_letsencrypt.json im Arbeitsverzeichnis angelegt. Befüllung erfolgt automatisch.
touch /opt/containers/traefik/data/acme_letsencrypt.json
chmod 600 /opt/containers/traefik/data/acme_letsencrypt.json
traefik konfigurieren
Dazu wird erneut eine Konfigurationsdatei ins Arbeitsverzeichnis geschrieben. Mit dem Editor deiner Wahl, bei mir vi.
vi /opt/containers/traefik/data/traefik.yml
Die einzelnen Abschnitte von oben nach unten…
api:
dashboard: true
certificatesResolvers:
http:
acme:
email: "sollte-deine-e@mail-se.in"
storage: "acme_letsencrypt.json"
httpChallenge:
entryPoint: http
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: "https"
scheme: "https"
https:
address: ":443"
global:
checknewversion: true
sendanonymoususage: false
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: "proxy"
file:
filename: "./dynamic_conf.yml"
watch: true
providersThrottleDuration: 10
In der YAML wird auf die Datei dynamic_conf.yml referenziert. Auch in dieser stehen Anpassungen und Direktiven für traefik, wie die Verschlüsselungsparameter, -algorithmen, Einstellungen zur Middleware, Headern usw.
vi /opt/containers/traefik/data/dynamic_conf.yml
Der Inhalt orientiert sich an nachfolgendem Eintrag. Dabei sollte man regelmäßig die ciperSuites kontrollieren. Ab und an fallen welche raus, die nicht mehr als sicher gelten.
tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
sniStrict: true
http:
middlewares:
traefikAuth:
basicAuth:
users:
# gehashten Wert eingeben / enter hashed value
- "dein-user:dein-passwort-hashwert"
default:
chain:
middlewares:
- default-security-headers
- gzip
secHeaders:
chain:
middlewares:
- default-security-headers
- gzip
default-security-headers:
headers:
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
frameDeny: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
customFrameOptionsValue: "SAMEORIGIN"
gzip:
compress: {}
In Zeile 21 der Datei sind Anpassungen vorzunehmen zur Definition eines Benutzernamen und Passwortes:
echo $(htpasswd -nb chef 'omlette-pommes-frites-mit-majo')
Den Rückgabewert wird passend eingefügt
middlewares:
traefikAuth:
basicAuth:
users:
- "chef:$apr1$BD.QzZIN$6OUwEXt5EtpxHi8gCngf/1"
default:
traefik Container > docker-compose.yml
Fertig für TL;DR zum schnellen kopieren in die eigene Umgebung. Die Erläuterung reiche ich nach. Daher wird das nachfolgende Kapitel ein „Work in progress“ sein.
version: '3.9'
services:
traefik:
container_name: traefik
image: traefik:latest
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme_letsencrypt.json:/acme_letsencrypt.json
- ./data/dynamic_conf.yml:/dynamic_conf.yml
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=https"
# die passende Domain einsetzen / enter the correct domain
- "traefik.http.routers.traefik.rule=Host(`traefik.DeineDomain.tld`)"
- "traefik.http.routers.traefik.middlewares=traefikAuth@file,default@file"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=http"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.services.traefik.loadbalancer.sticky.cookie.httpOnly=true"
- "traefik.http.services.traefik.loadbalancer.sticky.cookie.secure=true"
- "traefik.docker.network=proxy"
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
proxy:
hostname: traefik
ports:
- "80:80"
- "443:443"
networks:
proxy:
name: proxy
driver: bridge
attachable: true
Hier ist auf die Domain zu achten. Hinweis: idealerweise zeigt ein A-Record auf die IP des Servers.
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.rule=Host(`traefik.pommesbude-mit-majo.tld`)"
- "traefik.http.routers.traefik.middlewares=traefikAuth@file,default@file"
traefik Konfiguration verstehen
TL;DR – es folgt die blanke Theorie!
Auf alle Direktiven kann ich nicht eingehen. traefik gilt zwar als einfach, aber …. hahaha … naja, nein. Daher beschränke ich mich in dieser Anleitung, die ja das Ziel hat schnell ein Ergebnis zu liefern, auf die Anweisungen, die ich zum „Funktionieren“ brauche.
docker labels
Die labels: sind die Verbindung zwischen traefik und docker und begegnen Dir in allen Anleitungen, die auf docker + traefik aufsetzen.
Routers
Der Eintrag folgt dem Schema traefik.http.routers.<router_name>.<option>. Die <option> gibt dabei die Option an, die abweichend vom Standard geändert werden soll. Alle Referenzen gibt es in der traefik Dokumentation.
rule: gibt an, für welches spezifische Kriterium die rule (Regel) gültig sein soll (Ref.)
entrypoints: gibt an oder beschränkt den Anwendungsbereich von traefik auf bestimmte Einstiegspunkte (Ref.)
middlewares: mit middlewares werden die Anfragen verändert, bevor diese an den service weitergegeben werden. Dabei können die Anfragen, die Header modifiziert werden. Andere leiten die Anfragen um, oder fügen Authentifizierung hinzu… (Ref.1, Ref.2,)
service: das Ziel für die Anfragen (Ref.)
traefik starten
Ein integraler Bestandteil dieser Anleitung ist es, den Reverse Proxy traefik zu starten.
docker compose -f /opt/containers/traefik/docker-compose.yml up -d
Wenn richtig gemacht wurde, dann startet traefik seinen Dienst und wartet auf das „Einhaken“ weiterer Applikationen. Mit den entsprechenden labels versehen werde ich in weiteren Artikeln auch entsprechende Anwendungen einbinden. Die Quittung lass ich direkt ausgeben:
➜ ~ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
44b8150d0309 traefik:latest "/entrypoint.sh trae…" 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp traefik
Um jetzt in und mit traefik zu arbeiten, hatte ich die Domain mittels A-Record eingetragen. Wenn diese URL aufgerufen wird, dann öffnet sich ein http-Auth, die ich mit der Eingabe der Benutzer/Kennwort-Kombi von hier hinter mir lasse.

traefik Dashboard
Zusammenfassung
Ich habe in dieser Anleitung die Einrichtung von docker und die Bereitstellung von traefik als Reverse Proxy beschrieben und hier als handliche Bauanleitung zur Verfügung gestellt. Damit steht die Grundlage für weitere Anleitungen rund um docker-Container, die auf einem Server ihr Unwesen treiben. Abgesichert, administrierbar und einfach zu aktualisieren.
Womit geht es weiter?
Ich habe einige weitere, ergänzende Anleitungen erstellt, aber noch nicht auf die neue Plattform migriert. Zusammen mit neuen Anleitungen werde ich diese in absehbarer Zeit hier erneut anbieten.
- docker/traefik + Redmine
- docker/traefik + Bitwarden
- docker/traefik + Mailcow (work in progress)