Dieser Artikel befasst sich mit docker + traefik und ist die Grundlage einer Serie von Anleitungen zum Thema docker.
Update
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
Diese schlauen (?!) Worte stammen aus dem Buch „skalierbare Container-Infrastrukturen“ von Oliver Liebel. Ein Buch, dass ich in diesem Kontext guten Gewissens empfehlen kann.
A F F I L I A T E
Skalierbare Container-Infrastrukturen
In dem Buch werden viele Aspekte von Docker und der entsprechenden Orchestrierung beschrieben. Für alle die mehr wissen und probieren wollen!
Mit dem Klick und Kauf des Buchs links, unterstützt ihr meine Arbeit!
Ich sage Danke!
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.
Vorbereitungen
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 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
ZshIm 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
Zsh- 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
Zsh- 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
Zshdocker + docker compose installieren
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
Zshdocker 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, zB 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"
}
YAMLBei fixed-cidr-v6
muss deine 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
}
YAMLtraefik 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.
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.
Arbeitsverzeichnis(se)
Alle Container, die ich auf diesem Server installiere, werden unter /opt/containers
, in einem eigenen Unterverzeichnis liegen. Diesem Schema werden auch die weiteren Anleitungen und Artikel folgen.
mkdir -p /opt/containers/traefik/data
SSL/TLS mit Certbot
Die Anleitung hier ist dazu gedacht eine Anwendung über das Internet verfügbar zu machen. Stand der Dinge, der Technik und des guten Geschmacks ist die Absicherung mit SSL/TLS. Ergo erstelle ich im nächsten Schritt die Datei acme_letsencrypt.json
im Arbeitsverzeichnis. Diese Datei wird nicht manuell, sondern automatisch befüllt. Die Datei acme_letsencrypt.json
dient uns als Zertifikatsspeicher.
vi /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
ZshDie 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
YAMLIn der YAML wird auf die Datei dynamic_conf.yml
referenziert. Diese Datei lege ich als Nächstes an. Auch in dieser stehen Anpassungen und Direktiven für traefik
, wie die Verschlüsselungsparameter, -algorithmen, Einstellungen zur Middleware, Headern usw.
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: {}
YAMLIn Zeile 21 der Datei musst Du jetzt Anpassungen vornehmen. Dazu führst Du zunächst, an der Kommandozeile den folgenden – mit von Dir verwendetem Benutzernamen und Passwort – Befehl aus:
echo $(htpasswd -nb chef 'omlette-pommes-frites-mit-majo')
ZshDen Rückgabewert packst Du dann zusammen mit dem von Dir gewählten Benutzer, in die Zeile 21:
middlewares:
traefikAuth:
basicAuth:
users:
- "chef:$apr1$BD.QzZIN$6OUwEXt5EtpxHi8gCngf/1"
default:
YAMLtraefik Container > docker-compose.yml
Ich schreibe die Konfiguration hier einfach mal hin. Fertig für TL;DR zum schnellen kopieren in Deine 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
YAMLHier musst Du auf die Domain (Zeile 16) 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"
YAMLtraefik 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
ZshWenn ich alles richtig gemacht habe, 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
ZshUm 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.
Zusammenfassung
Ich habe in dieser Anleitung die Einrichtung von docker
und die Bereitstellung von traefik
als Reverse Proxy beschrieben und Dir hier als handliche Bauanleitung zur Verfügung gestellt. Damit steht die Grundlage für weitere Anleitungen rund um docker.
Womit geht es weiter?
Ich habe mittlerweile einige weitere, ergänzende Anleitungen erstellt.
Docker + Redmine
Docker + Bitwarden
Quellen
Install Docker Engine on Ubuntu
How to install and use Docker on Ubuntu 22.04
IPv6 in Docker
goneuland.de
Compose File Reference
traefik Dokumentation
3 Gedanken zu „Docker + Traefik“