Docker Stack Traefik: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(Die Seite wurde geleert.) Markierung: Geleert |
|||
| Zeile 1: | Zeile 1: | ||
| + | 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 <code>docker-compose.yml</code>. Jedes Projekt ist unabhängig start- und stoppbar. | ||
| + | |||
| + | ; Gemeinsames externes Netz | ||
| + | * Das Netz <code>proxy</code> wird einmalig von Hand angelegt. Traefik hängt sich hinein, die Anwendungen treten ihm als <code>external</code> 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 <code>/etc/ssl/own.crt</code> und <code>/etc/ssl/own.key</code> 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== | ||
| + | |||
| + | <pre> | ||
| + | docker/ | ||
| + | ├── traefik/ | ||
| + | │ ├── docker-compose.yml | ||
| + | │ └── dynamic/ | ||
| + | │ └── tls.yml | ||
| + | ├── nextcloud/ | ||
| + | │ └── docker-compose.yml | ||
| + | └── mediawiki/ | ||
| + | └── docker-compose.yml | ||
| + | </pre> | ||
| + | |||
| + | ==Externes Netz anlegen== | ||
| + | |||
| + | Einmalig, bevor irgendein Projekt startet: | ||
| + | |||
| + | ; Proxy-Netz erstellen | ||
| + | * <code>docker network create proxy</code> | ||
| + | |||
| + | ==Projekt 1: Traefik== | ||
| + | |||
| + | Verzeichnis <code>traefik/</code>. | ||
| + | |||
| + | ===traefik/docker-compose.yml=== | ||
| + | |||
| + | <syntaxhighlight lang="yaml"> | ||
| + | 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 | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ===traefik/dynamic/tls.yml=== | ||
| + | |||
| + | <syntaxhighlight lang="yaml"> | ||
| + | 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 | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ; 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 <code>default</code>-Store reicht an jedem Router ein einfaches <code>tls=true</code>. 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 <code>nextcloud/</code>. | ||
| + | |||
| + | ===nextcloud/docker-compose.yml=== | ||
| + | |||
| + | <syntaxhighlight lang="yaml"> | ||
| + | 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: | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ; Zwei Netze | ||
| + | * Der Web-Container hängt an <code>proxy</code> (für Traefik) und an <code>back</code> (für die DB). Die Datenbank hängt '''nur''' an <code>back</code> 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 <code>mediawiki/</code>. | ||
| + | |||
| + | ===mediawiki/docker-compose.yml=== | ||
| + | |||
| + | <syntaxhighlight lang="yaml"> | ||
| + | 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: | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ; Gleiche Struktur wie Nextcloud | ||
| + | * Eigene DB im internen <code>back</code>-Netz, der Web-Container zusätzlich am <code>proxy</code>-Netz für Traefik. | ||
| + | |||
| + | ==Inbetriebnahme== | ||
| + | |||
| + | Reihenfolge: erst das Netz, dann Traefik, dann die Anwendungen. | ||
| + | |||
| + | ; Externes Netz anlegen (einmalig) | ||
| + | * <code>docker network create proxy</code> | ||
| + | |||
| + | ; Zertifikat ablegen | ||
| + | * <code>cd traefik && ./get-cert.sh</code> | ||
| + | |||
| + | ; Traefik starten | ||
| + | * <code>cd traefik && docker compose up -d</code> | ||
| + | |||
| + | ; Nextcloud starten | ||
| + | * <code>cd ../nextcloud && docker compose up -d</code> | ||
| + | |||
| + | ; MediaWiki starten | ||
| + | * <code>cd ../mediawiki && docker compose up -d</code> | ||
| + | |||
| + | ; Status je Projekt prüfen | ||
| + | * <code>docker compose ps</code> | ||
| + | |||
| + | ==DNS== | ||
| + | |||
| + | Beide Hostnamen müssen auf den Docker-Host zeigen: | ||
| + | |||
| + | ; Nextcloud | ||
| + | * <code>cloud.it2XX.xinmen.de.int</code> | ||
| + | |||
| + | ; MediaWiki | ||
| + | * <code>wiki.it2XX.xinmen.de.int</code> | ||
| + | |||
| + | ==MediaWiki-Setup abschließen== | ||
| + | |||
| + | ; Erstaufruf im Browser | ||
| + | * MediaWiki startet ohne <code>LocalSettings.php</code> mit dem Web-Installer. Als Datenbank-Host <code>mediawiki-db</code>, Datenbank <code>mediawiki</code>, Benutzer <code>mediawiki</code> angeben. | ||
| + | |||
| + | ; LocalSettings.php einhängen | ||
| + | * Nach dem Setup die generierte <code>LocalSettings.php</code> ins <code>mediawiki/</code>-Verzeichnis legen, den auskommentierten Volume-Mount aktivieren und den Container neu starten. | ||
| + | * <code>docker compose up -d mediawiki</code> | ||
Aktuelle Version vom 27. Juni 2026, 16:26 Uhr
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
proxywird einmalig von Hand angelegt. Traefik hängt sich hinein, die Anwendungen treten ihm alsexternalbei. 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.crtund/etc/ssl/own.keyund 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 einfachestls=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 anback(für die DB). Die Datenbank hängt nur anbackund 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 amproxy-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.phpmit dem Web-Installer. Als Datenbank-Hostmediawiki-db, Datenbankmediawiki, Benutzermediawikiangeben.
- LocalSettings.php einhängen
- Nach dem Setup die generierte
LocalSettings.phpinsmediawiki/-Verzeichnis legen, den auskommentierten Volume-Mount aktivieren und den Container neu starten. docker compose up -d mediawiki