Docker Stack Traefik
Version vom 27. Juni 2026, 16:13 Uhr von Thomas.will (Diskussion | Beiträge)
Dieser Artikel beschreibt einen Docker-Compose-Stack mit Traefik als Reverse-Proxy und den beiden Webanwendungen Nextcloud und MediaWiki, die jeweils eine eigene, getrennte MariaDB erhalten. Traefik erkennt die Container automatisch über Labels und terminiert TLS mit einem statischen Wildcard-Zertifikat.
Konzept
- Traefik als Reverse-Proxy
- Im Gegensatz zu HAProxy werden die Backends nicht von Hand konfiguriert. Traefik liest die Docker-Labels der Container und erzeugt Router und Services dynamisch.
- Statisches Zertifikat
- Im Lab gibt es kein ACME/Let's-Encrypt nach außen. Das Wildcard-Zertifikat liegt unter
/etc/ssl/own.crtund/etc/ssl/own.keyund wird per File-Provider als Default registriert.
- Pro App eine eigene Datenbank
- Jede Anwendung bekommt einen eigenen MariaDB-Container in einem eigenen Backend-Netz. Es gibt keine gemeinsame Datenbank. Eine kompromittierte Anwendung kann damit nicht über eine geteilte DB an die Daten der anderen Anwendung gelangen.
Netz-Trennung
- proxy
- Verbindet Traefik mit den Webanwendungen.
- nextcloud-back
- Verbindet nur Nextcloud mit seiner Datenbank.
- mediawiki-back
- Verbindet nur MediaWiki mit seiner Datenbank.
Die beiden DB-Container hängen jeweils nur an ihrem eigenen Backend-Netz und sind weder von außen noch von der jeweils anderen Anwendung erreichbar.
Verzeichnisstruktur
docker-stack/
├── docker-compose.yml
└── traefik/
└── dynamic/
└── tls.yml
docker-compose.yml
services:
# Traefik - Reverse Proxy (statisches Wildcard-Cert)
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.file.directory=/etc/traefik/dynamic"
- "--providers.file.watch=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik/dynamic:/etc/traefik/dynamic:ro"
- "/etc/ssl/own.crt:/etc/ssl/own.crt:ro"
- "/etc/ssl/own.key:/etc/ssl/own.key:ro"
networks:
- proxy
# Nextcloud + eigene DB
nextcloud-db:
image: mariadb:11
container_name: nextcloud-db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
environment:
MARIADB_ROOT_PASSWORD: nc-rootpass
MARIADB_DATABASE: nextcloud
MARIADB_USER: nextcloud
MARIADB_PASSWORD: nextcloudpass
MARIADB_AUTO_UPGRADE: "1"
volumes:
- nextcloud_db:/var/lib/mysql
networks:
- nextcloud-back
nextcloud:
image: nextcloud:30-apache
container_name: nextcloud
restart: unless-stopped
depends_on:
- nextcloud-db
environment:
MYSQL_HOST: nextcloud-db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: nextcloudpass
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: adminpass
NEXTCLOUD_TRUSTED_DOMAINS: cloud.it2XX.xinmen.de.int
OVERWRITEPROTOCOL: https
volumes:
- nextcloud_data:/var/www/html
networks:
- proxy
- nextcloud-back
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`cloud.it2XX.xinmen.de.int`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls=true"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
- "traefik.http.middlewares.nc-dav.redirectregex.regex=https://([^/]*)/.well-known/(card|cal)dav"
- "traefik.http.middlewares.nc-dav.redirectregex.replacement=https://$${1}/remote.php/dav/"
- "traefik.http.routers.nextcloud.middlewares=nc-dav"
# MediaWiki + eigene DB
mediawiki-db:
image: mariadb:11
container_name: mediawiki-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: mw-rootpass
MARIADB_DATABASE: mediawiki
MARIADB_USER: mediawiki
MARIADB_PASSWORD: mediawikipass
MARIADB_AUTO_UPGRADE: "1"
volumes:
- mediawiki_db:/var/lib/mysql
networks:
- mediawiki-back
mediawiki:
image: mediawiki:1.43
container_name: mediawiki
restart: unless-stopped
depends_on:
- mediawiki-db
volumes:
- mediawiki_data:/var/www/html/images
# LocalSettings.php nach dem Setup einhaengen:
# - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro
networks:
- proxy
- mediawiki-back
labels:
- "traefik.enable=true"
- "traefik.http.routers.mediawiki.rule=Host(`wiki.it2XX.xinmen.de.int`)"
- "traefik.http.routers.mediawiki.entrypoints=websecure"
- "traefik.http.routers.mediawiki.tls=true"
- "traefik.http.services.mediawiki.loadbalancer.server.port=80"
networks:
proxy:
nextcloud-back:
mediawiki-back:
volumes:
nextcloud_db:
nextcloud_data:
mediawiki_db:
mediawiki_data:
Erklärung der Bausteine
Traefik
- Docker-Provider mit Opt-in
exposedbydefault=falsesorgt dafür, dass nur Container mittraefik.enable=trueveröffentlicht werden. Alles andere bleibt unsichtbar.
- File-Provider für TLS
- Das statische Zertifikat wird nicht über Labels, sondern über eine Datei eingebunden (siehe
tls.yml).watch=truelädt Änderungen ohne Neustart.
- HTTP→HTTPS-Redirect global
- Die beiden
redirections-Zeilen leiten den gesamten Port-80-Verkehr auf HTTPS um. Das muss kein Container selbst regeln.
- Docker-Socket read-only
- Traefik liest die Container-Labels über den Docker-Socket. Der wird read-only gemountet.
Datenbanken
- Anlage über Umgebungsvariablen
- Jeder MariaDB-Container legt Datenbank und Benutzer beim ersten Start selbst an, gesteuert über
MARIADB_DATABASE,MARIADB_USERundMARIADB_PASSWORD. Ein separates Init-Skript ist nicht nötig.
- Getrennte Volumes
nextcloud_dbundmediawiki_dbsind voneinander unabhängige Volumes. Jede DB hat ihren eigenen Datenbestand.
Traefik Dynamic Config (tls.yml)
Pfad im Container: /etc/traefik/dynamic/tls.yml
tls:
certificates:
- certFile: /etc/ssl/own.crt
keyFile: /etc/ssl/own.key
stores:
default:
defaultCertificate:
certFile: /etc/ssl/own.crt
keyFile: /etc/ssl/own.key
- Default-Zertifikat
- Durch das
default-Store reicht an jedem Router ein einfachestls=true. Traefik greift automatisch auf dieses Zertifikat zurück, ein eigener Cert-Verweis pro Router entfällt.
Inbetriebnahme
- Zertifikat ablegen
- Das Wildcard-Zertifikat zur Domain mit dem vorhandenen Skript ziehen, sodass
/etc/ssl/own.crtund/etc/ssl/own.keyvorhanden sind. ./get-cert.sh
- Stack starten
docker compose up -d
- Status prüfen
docker compose ps
- Logs verfolgen
docker compose logs -f traefik
DNS
Die beiden Hostnamen müssen auf den Docker-Host zeigen:
- Nextcloud
cloud.it2XX.xinmen.de.int
- MediaWiki
wiki.it2XX.xinmen.de.int
MediaWiki-Setup abschließen
- Erstaufruf im Browser
- MediaWiki startet ohne
LocalSettings.phpmit dem Web-Installer. Als Datenbank-Hostmediawiki-db, Datenbankmediawiki, Benutzermediawikiangeben.
- LocalSettings.php einhängen
- Nach dem Setup wird die generierte
LocalSettings.phpheruntergeladen, neben das Compose-File gelegt und der auskommentierte Volume-Mount immediawiki-Service aktiviert. Danach Container neu starten. docker compose up -d mediawiki