Einfaches Multi-Projekt-Setup mit Docker-Composite und Traefik.
Um Projekte auf einem Server zu hosten gibt es viele Wege und keiner ist falsch. Gerade bei kleineren Projekten oder Servern hilft ein leichtgewichtiges und wartungsarmes Setup. Durch den Verzicht auf Skalierung kann auch auf große, ressourcenhungrige Tools wie Kubernetes verzichtet werden.
Um den Wartungsaufwand gering zu halten, setzt das Setup ausschließlich auf Docker und Docker-Compose.
Jedes Projekt erhält einen Ordner mit einer eigenen Docker-Compose. In dieser werden alle Container definiert. Der Traffic wird über Traefik zum jeweiligen Projekt geleitet. Die Konfiguration von Traefik ist live über Label in der jeweiligen Compose Datei möglich.
Wenn konfiguriert, kümmert sich Traefik automatisch um TLS Zertifikate per Let’s Encrypt.
Der spätere Verzeichnis Aufbau:
- projects
- traefik
- docker-compose.yml
- traefik.yml
- acme.json
- projectA
- docker-compose.yml
Netzwerk link
Docker-Compose ermöglicht es, Container in mehrere Netzwerke einzubinden. Für alle Container, die aus dem Internet erreichbar sein sollen, wird ein Netzwerk benötigt.
docker network create web
Proxy Traefik link
In einem eigenen Ordner für Traefik muss eine Docker-Compose docker-compose.yml
Datei angelegt werden.
Traefik wird als einziger Container auf den Ports 80
und 443
lauschen und alle Anfragen intern weiterleiten. Damit Traefik live auf Änderungen reagieren kann, muss der Container Zugriff auf /var/run/docker.sock
haben.
In der Datei acme.json
speichert Traefik die Let’s Encrypt Zertifikate.
version: '3.7'
services:
traefik:
image: traefik:2.6
restart: always
ports:
- 80:80
- 443:443
logging:
options:
max-size: "10m"
max-file: "3"
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/traefik.yml
- ./acme.json:/acme.json
networks:
web:
external: true
Konfiguration link
Traefik kann über Labels am Container konfiguriert werden. Einfacher geht es jedoch mit einer traefik.yml
Datei.
Zunächst müssen die entryPoints
definiert werden, an denen Traefik eingehenden Traffic erwartet. Neben HTTP(S) sind hier auch TCP/UDP Verbindungen möglich.
Als Provider ist Docker konfiguriert. Durch die Einstellung exposedByDefault: false
werden Container erst öffentlich, wenn dies am Container aktiviert wird. Gibt einfach etwas mehr Sicherheit.
log:
level: INFO
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
exposedByDefault: false
network: web
endpoint: "unix:///var/run/docker.sock"
watch: true
serversTransport:
insecureSkipVerify: true
api:
dashboard: true
accessLog: {}
TLS-Zertifikate link
An jedem Container kann definiert werden, wie das TLS Zertifikat entsteht. Für eine einfache Konfiguration kann hier ein ACME/Let’s Encrypt Resolver verwendet werden. Dieser erstellt auf dem HTTP-Endpunkt eine eigene Route, über die Let’s Encrypt die Domain verifizieren kann.
Läuft der Traefik in einem privaten Netzwerk, das von außen nicht erreichbar ist, kann hier auch der DNS Resolver verwendet werden. Dieser hinterlegt die benötigten Daten automatisch beim DNS-Server.
Folgender Codeausschnitt gehört an das Ende der Datei traefik.yml
. Der gewählte Name des Resolvers (hier sample-resolver
) wird später benötigt.
certificatesResolvers:
sample-resolver:
acme:
email: <email@example.com>
storage: /acme.json
httpChallenge:
# used during the challenge
entryPoint: http
Start link
Wie gewohnt kann traefik nun mit Docker-Compose gestartet werden.
docker-compose up -d
Von nun an wird Traefik seine Konfiguration automatisch aktualisieren, wenn Projekte gestartet, beendet oder neu konfiguriert werden.
Projekte link
In den jeweiligen Projekt Ordnern kann wie gewohnt eine Docker-Compose Datei erstellt werden. Diese wird nur zusätzlich um Netzwerk und Labels erweitert.
version: '3.7'
services:
app:
# ...
networks:
- web
labels:
- traefik.enable=true
- traefik.http.routers.my-container.rule=Host(`example.com`)
- traefik.http.services.my-service.loadbalancer.server.port=12345
- traefik.docker.network=web
networks:
web:
external: true
Netzwerk link
Unter dem Punkt networks
kann eine Liste von Netzwerken definiert werden. Der zuvor erstellte Traefik Server befindet sich im Netzwerk web
. Container, wie z.B. die Datenbank, die nicht von außen erreichbar sein sollen, können z.B. in ein Netzwerk backend
gepackt werden. Wenn z.B. die App und die Datenbank im Netzwerk backend
sind, können nur diese miteinander Daten austauschen. Aber nur die Anwendung mit der Datenbank.
docker network create web
Label link
Für das jeweilige Projekt sind von Traefik die Router, Middlewares und Services interessant. In Traffic können Router, Services und Middlewares wiederverwendet werden. Im Docker Ansatz finde ich das sehr unübersichtlich, daher verwende ich hier für jeden Container im Label einen eigenen Namen.
Es ist auch möglich mehrere Router, Middlewares oder Service Endpunkte für den Container zu definieren. Bei mir ist z.B. /metrics
nur über einen speziellen Traefik Endpunkt erreichbar, der nicht global auf Port 80 hört und über eine interne Netzwerkkarte erreichbar ist. So kann nur mein Prometheus Server die Daten über das virtuelle Netzwerk abrufen.
Router und Service link
Die Router Label beschreiben, wann der Traffic in das Projekt geroutet wird. Die Router Rule kann viele verschiedene Parameter des Requests berücksichtigen und auch aus mehreren Kombinationen bestehen. Hier im Beispiel wird die verwendete Domain validiert. Es kann aber z.B. auch nach dem Präfix des Pfades geprüft werden.
Die Loadbalancer Anweisung definiert auf welchem Port der Container Traffic erwartet.
- traefik.http.routers.my-container.rule=Host(`example.com`)
- traefik.http.services.my-service.loadbalancer.server.port=12345