Docker Stack Traefik
Version vom 27. Juni 2026, 16:06 Uhr von Thomas.will (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „Dieser Artikel beschreibt einen kompletten Docker-Compose-Stack mit '''Traefik''' als Reverse-Proxy, einer gemeinsamen '''MariaDB''' und den beiden Webanwendun…“)
Dieser Artikel beschreibt einen kompletten Docker-Compose-Stack mit Traefik als Reverse-Proxy, einer gemeinsamen MariaDB und den beiden Webanwendungen Nextcloud und MediaWiki. 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.
- Eine Datenbank für beide Apps
- Ein gemeinsamer MariaDB-Container hält zwei getrennte Datenbanken (
nextcloudundmediawiki) mit jeweils eigenem Benutzer.
Verzeichnisstruktur
docker-stack/
├── docker-compose.yml
├── traefik/
│ └── dynamic/
│ └── tls.yml
└── db-init/
└── 01-init.sql
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
# MariaDB - gemeinsame DB fuer Nextcloud + MediaWiki
db:
image: mariadb:11
container_name: db
restart: unless-stopped
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
environment:
MARIADB_ROOT_PASSWORD: rootpass
MARIADB_AUTO_UPGRADE: "1"
volumes:
- db_data:/var/lib/mysql
- ./db-init:/docker-entrypoint-initdb.d:ro
networks:
- backend
# Nextcloud
nextcloud:
image: nextcloud:30-apache
container_name: nextcloud
restart: unless-stopped
depends_on:
- db
environment:
MYSQL_HOST: 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
- backend
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
mediawiki:
image: mediawiki:1.43
container_name: mediawiki
restart: unless-stopped
depends_on:
- db
volumes:
- mediawiki_data:/var/www/html/images
# LocalSettings.php nach dem Setup einhaengen:
# - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro
networks:
- proxy
- backend
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:
backend:
volumes:
db_data:
nextcloud_data:
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.
MariaDB
- Gemeinsame Datenbank
- Ein Container, zwei Datenbanken. Die Anlage übernimmt das Init-Skript (siehe unten), das beim ersten Start automatisch ausgeführt wird.
- Transaction-Isolation
READ-COMMITTEDundbinlog-format=ROWsind die von Nextcloud empfohlenen Einstellungen.
Netze
- Zwei Netze trennen Front und Back
proxyverbindet Traefik mit den Webanwendungen.backendverbindet die Webanwendungen mit der Datenbank. Die DB hängt nicht am Proxy-Netz und ist damit von außen nicht erreichbar.
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.
Datenbank-Init (01-init.sql)
Pfad: ./db-init/01-init.sql – wird beim ersten Start von MariaDB automatisch ausgeführt.
CREATE DATABASE IF NOT EXISTS nextcloud
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'nextcloud'@'%' IDENTIFIED BY 'nextcloudpass';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'%';
CREATE DATABASE IF NOT EXISTS mediawiki
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS 'mediawiki'@'%' IDENTIFIED BY 'mediawikipass';
GRANT ALL PRIVILEGES ON mediawiki.* TO 'mediawiki'@'%';
FLUSH PRIVILEGES;
- Nur beim ersten Start
- Das Init-Verzeichnis wird nur ausgeführt, solange das Datenverzeichnis
db_dataleer ist. Bei einem späteren Lauf muss man die Datenbanken von Hand anlegen oder das Volume löschen.
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-Hostdb, 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