Docker Stack Traefik

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Dieser Artikel beschreibt einen Docker-Aufbau, bei dem Traefik als zentraler Reverse-Proxy in einem eigenen Projekt läuft und die Anwendungen Nextcloud und MediaWiki als jeweils eigenständige Compose-Projekte betrieben werden. Die Verbindung erfolgt über ein gemeinsames, extern angelegtes Docker-Netz. Jede Anwendung bringt ihre eigene Datenbank mit. Traefik terminiert TLS mit einem statischen Wildcard-Zertifikat.

Konzept

Drei getrennte Projekte
  • Traefik, Nextcloud und MediaWiki liegen in drei eigenen Verzeichnissen mit jeweils eigener docker-compose.yml. Jedes Projekt ist unabhängig start- und stoppbar.
Gemeinsames externes Netz
  • Das Netz proxy wird einmalig von Hand angelegt. Traefik hängt sich hinein, die Anwendungen treten ihm als external bei. So findet Traefik die Container, ohne dass alles in einem Compose-File stehen muss.
Statisches Zertifikat
  • Im Lab gibt es kein ACME 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.
Pro App eine eigene Datenbank
  • Jede Anwendung hat einen eigenen MariaDB-Container in einem eigenen, app-internen Netz. Es gibt keine gemeinsame Datenbank. Eine kompromittierte Anwendung kann nicht an die Daten der anderen gelangen.

Verzeichnisstruktur

docker/
├── traefik/
│   ├── docker-compose.yml
│   └── dynamic/
│       └── tls.yml
├── nextcloud/
│   └── docker-compose.yml
└── mediawiki/
    └── docker-compose.yml

Externes Netz anlegen

Einmalig, bevor irgendein Projekt startet:

Proxy-Netz erstellen
  • docker network create proxy

Projekt 1: Traefik

Verzeichnis traefik/.

traefik/docker-compose.yml

services:
  traefik:
    image: traefik:v3.3
    container_name: traefik
    restart: unless-stopped
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=proxy"
      - "--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"
      - "./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

networks:
  proxy:
    external: true

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
provider.docker.network=proxy
  • Sagt Traefik, über welches Netz die Backends erreichbar sind. Wichtig, sobald Container an mehreren Netzen hängen.
Default-Zertifikat
  • Durch das default-Store reicht an jedem Router ein einfaches tls=true. Ein eigener Cert-Verweis pro Router entfällt.
external
true
  • Das Netz wird nicht von diesem Projekt erzeugt, sondern als bereits vorhanden vorausgesetzt (siehe oben).

Projekt 2: Nextcloud

Verzeichnis nextcloud/.

nextcloud/docker-compose.yml

services:
  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:
      - db:/var/lib/mysql
    networks:
      - 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:
      - data:/var/www/html
    networks:
      - proxy
      - 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"

networks:
  proxy:
    external: true
  back:

volumes:
  db:
  data:
Zwei Netze
  • Der Web-Container hängt an proxy (für Traefik) und an back (für die DB). Die Datenbank hängt nur an back und ist damit weder von außen noch von anderen Projekten erreichbar.
DB-Anlage über Env
  • MariaDB legt Datenbank und Benutzer beim ersten Start selbst an. Kein Init-Skript nötig.

Projekt 3: MediaWiki

Verzeichnis mediawiki/.

mediawiki/docker-compose.yml

services:
  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:
      - db:/var/lib/mysql
    networks:
      - back

  mediawiki:
    image: mediawiki:1.43
    container_name: mediawiki
    restart: unless-stopped
    depends_on:
      - mediawiki-db
    volumes:
      - data:/var/www/html/images
      # LocalSettings.php nach dem Setup einhaengen:
      # - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro
    networks:
      - proxy
      - 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:
    external: true
  back:

volumes:
  db:
  data:
Gleiche Struktur wie Nextcloud
  • Eigene DB im internen back-Netz, der Web-Container zusätzlich am proxy-Netz für Traefik.

Inbetriebnahme

Reihenfolge: erst das Netz, dann Traefik, dann die Anwendungen.

Externes Netz anlegen (einmalig)
  • docker network create proxy
Zertifikat ablegen
  • cd traefik && ./get-cert.sh
Traefik starten
  • cd traefik && docker compose up -d
Nextcloud starten
  • cd ../nextcloud && docker compose up -d
MediaWiki starten
  • cd ../mediawiki && docker compose up -d
Status je Projekt prüfen
  • docker compose ps

DNS

Beide 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 mediawiki-db, Datenbank mediawiki, Benutzer mediawiki angeben.
LocalSettings.php einhängen
  • Nach dem Setup die generierte LocalSettings.php ins mediawiki/-Verzeichnis legen, den auskommentierten Volume-Mount aktivieren und den Container neu starten.
  • docker compose up -d mediawiki