Docker Stack Traefik: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
(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…“) |
|||
| (3 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
| − | Dieser Artikel beschreibt einen | + | 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== | ==Konzept== | ||
| − | ; Traefik | + | ; 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 | ; Statisches Zertifikat | ||
| − | * Im Lab gibt es kein ACME | + | * 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== | ==Verzeichnisstruktur== | ||
<pre> | <pre> | ||
| − | docker | + | docker/ |
| − | |||
├── traefik/ | ├── traefik/ | ||
| + | │ ├── docker-compose.yml | ||
│ └── dynamic/ | │ └── dynamic/ | ||
│ └── tls.yml | │ └── tls.yml | ||
| − | └── | + | ├── nextcloud/ |
| − | └── | + | │ └── docker-compose.yml |
| + | └── mediawiki/ | ||
| + | └── docker-compose.yml | ||
</pre> | </pre> | ||
| − | ==docker-compose.yml== | + | ==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"> | <syntaxhighlight lang="yaml"> | ||
services: | services: | ||
| − | |||
| − | |||
traefik: | traefik: | ||
image: traefik:v3.3 | image: traefik:v3.3 | ||
| Zeile 37: | Zeile 51: | ||
- "--providers.docker=true" | - "--providers.docker=true" | ||
- "--providers.docker.exposedbydefault=false" | - "--providers.docker.exposedbydefault=false" | ||
| + | - "--providers.docker.network=proxy" | ||
- "--providers.file.directory=/etc/traefik/dynamic" | - "--providers.file.directory=/etc/traefik/dynamic" | ||
- "--providers.file.watch=true" | - "--providers.file.watch=true" | ||
| Zeile 48: | Zeile 63: | ||
volumes: | volumes: | ||
- "/var/run/docker.sock:/var/run/docker.sock:ro" | - "/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.crt:/etc/ssl/own.crt:ro" | ||
- "/etc/ssl/own.key:/etc/ssl/own.key:ro" | - "/etc/ssl/own.key:/etc/ssl/own.key:ro" | ||
| Zeile 54: | Zeile 69: | ||
- proxy | - proxy | ||
| − | + | networks: | |
| − | db: | + | 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 | image: mariadb:11 | ||
| − | container_name: db | + | container_name: nextcloud-db |
restart: unless-stopped | restart: unless-stopped | ||
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW | command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW | ||
environment: | environment: | ||
| − | MARIADB_ROOT_PASSWORD: rootpass | + | MARIADB_ROOT_PASSWORD: nc-rootpass |
| + | MARIADB_DATABASE: nextcloud | ||
| + | MARIADB_USER: nextcloud | ||
| + | MARIADB_PASSWORD: nextcloudpass | ||
MARIADB_AUTO_UPGRADE: "1" | MARIADB_AUTO_UPGRADE: "1" | ||
volumes: | volumes: | ||
| − | - | + | - db:/var/lib/mysql |
| − | |||
networks: | networks: | ||
| − | - | + | - back |
| − | |||
nextcloud: | nextcloud: | ||
image: nextcloud:30-apache | image: nextcloud:30-apache | ||
| Zeile 75: | Zeile 126: | ||
restart: unless-stopped | restart: unless-stopped | ||
depends_on: | depends_on: | ||
| − | - db | + | - nextcloud-db |
environment: | environment: | ||
| − | MYSQL_HOST: db | + | MYSQL_HOST: nextcloud-db |
MYSQL_DATABASE: nextcloud | MYSQL_DATABASE: nextcloud | ||
MYSQL_USER: nextcloud | MYSQL_USER: nextcloud | ||
| Zeile 86: | Zeile 137: | ||
OVERWRITEPROTOCOL: https | OVERWRITEPROTOCOL: https | ||
volumes: | volumes: | ||
| − | - | + | - data:/var/www/html |
networks: | networks: | ||
- proxy | - proxy | ||
| − | - | + | - back |
labels: | labels: | ||
- "traefik.enable=true" | - "traefik.enable=true" | ||
| Zeile 100: | Zeile 151: | ||
- "traefik.http.routers.nextcloud.middlewares=nc-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: | mediawiki: | ||
image: mediawiki:1.43 | image: mediawiki:1.43 | ||
| Zeile 106: | Zeile 195: | ||
restart: unless-stopped | restart: unless-stopped | ||
depends_on: | depends_on: | ||
| − | - db | + | - mediawiki-db |
volumes: | volumes: | ||
| − | - | + | - data:/var/www/html/images |
# LocalSettings.php nach dem Setup einhaengen: | # LocalSettings.php nach dem Setup einhaengen: | ||
# - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro | # - ./LocalSettings.php:/var/www/html/LocalSettings.php:ro | ||
networks: | networks: | ||
- proxy | - proxy | ||
| − | - | + | - back |
labels: | labels: | ||
- "traefik.enable=true" | - "traefik.enable=true" | ||
| Zeile 123: | Zeile 212: | ||
networks: | networks: | ||
proxy: | proxy: | ||
| − | + | external: true | |
| + | back: | ||
volumes: | volumes: | ||
| − | + | db: | |
| − | + | data: | |
| − | |||
</syntaxhighlight> | </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> | + | * <code>cd traefik && docker compose up -d</code> |
| − | + | ; Nextcloud starten | |
| + | * <code>cd ../nextcloud && docker compose up -d</code> | ||
| − | ; | + | ; MediaWiki starten |
| − | * <code> | + | * <code>cd ../mediawiki && docker compose up -d</code> |
| − | + | ; Status je Projekt prüfen | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | ; Status prüfen | ||
* <code>docker compose ps</code> | * <code>docker compose ps</code> | ||
| − | |||
| − | |||
| − | |||
==DNS== | ==DNS== | ||
| − | + | Beide Hostnamen müssen auf den Docker-Host zeigen: | |
; Nextcloud | ; Nextcloud | ||
| Zeile 228: | Zeile 258: | ||
; Erstaufruf im Browser | ; Erstaufruf im Browser | ||
| − | * MediaWiki startet ohne <code>LocalSettings.php</code> mit dem Web-Installer. Als Datenbank-Host <code>db</code>, Datenbank <code>mediawiki</code>, Benutzer <code>mediawiki</code> angeben. | + | * 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 | ; LocalSettings.php einhängen | ||
| − | * Nach dem Setup | + | * 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> | * <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