Docker Stack Traefik

Aus Xinux Wiki
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…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

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.crt und /etc/ssl/own.key und wird per File-Provider als Default registriert.
Eine Datenbank für beide Apps
  • Ein gemeinsamer MariaDB-Container hält zwei getrennte Datenbanken (nextcloud und mediawiki) 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=false sorgt dafür, dass nur Container mit traefik.enable=true verö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=true lä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-COMMITTED und binlog-format=ROW sind die von Nextcloud empfohlenen Einstellungen.

Netze

Zwei Netze trennen Front und Back
  • proxy verbindet Traefik mit den Webanwendungen. backend verbindet 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 einfaches tls=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_data leer 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.crt und /etc/ssl/own.key vorhanden 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.php mit dem Web-Installer. Als Datenbank-Host db, Datenbank mediawiki, Benutzer mediawiki angeben.
LocalSettings.php einhängen
  • Nach dem Setup wird die generierte LocalSettings.php heruntergeladen, neben das Compose-File gelegt und der auskommentierte Volume-Mount im mediawiki-Service aktiviert. Danach Container neu starten.
  • docker compose up -d mediawiki