Letzte Aktualisierung am 20. April 2025


Ich hatte in der Vergangenheit über meinen DSL-Anschluss den ein oder anderen Dienst im Internet bereitgestellt nach den einschlägigen Anleitungen, die man für dynamische DNS-Auflösung mit eigener, öffentlichen IPv4-Adressen im Internet findet.

Das ganze hat sich allerdings geändert als ich meinen DSL- durch einen Glasfaser-Anschluss ersetzt habe und damit die eigene, öffentliche IPv4-Adresse durch eine geteilte an einem DS-Lite ersetzt wurde. Auch für DS-Lite gibt es im Internet eine Vielzahl an Anleitungen, um Dienst im Internet bereitzustellen.

Nach mehreren Versuchen, unterbrochen von einigen Pause und einer Wiederaufnahme im letzten Jahr habe ich mich schließlich entschieden, Dienste über Cloudflare ins Internet zu stellen, das ganze zusammen mit Traefik als Reverse Proxy für die korrekte Ansteuerung einzelner Docker-Container.

Mein Vorgehen dazu beschreibe ich in diesem Artikel, es basiert auf dem Blog-Artikel von Gero Gerke.


Voraussetzungen

Top-Level-Domain

Wir werden später für die einzelnen Dienste eigene Subdomains verwenden. Dafür ist es notwendig, dass du eine eigene Top-Level-Domain www.meine-domain.de bei einem Webhoster registriert hast. Du benötigst kein Webhosting-Paket, eine registrierte Domain ist vollkommen ausreichend. Du musst allerdings darauf achten, dass du bei deiner Domain die Nameserver im DNS-Record ändern kannst, was später in Verbindung mit Cloudflare wichtig ist.

ACHTUNG: Durch die Änderung der Nameserver auf diejenigen von Cloudflare ist deine Top-Level-Domain erstmal nicht mehr über deinen Hosting-Anbieter erreichbar!

Du musst keine Subdomain für deine Domain anlegen, das erledigen wir später mit Cloudflare.

Cloudflare

Ein Hinweis vorweg: Cloudflare ist ein US-amerikanisches Unternehmen, daher ist damit zu rechnen, dass eigene Daten in die USA wandern. Cloudflare betreibt Server in Deutschland, über die i.d.R. deine angelegten Tunnel laufen. Allerdings ist das nicht garantiert. Über die Metriken von cloudflared kann man sehen, über welchen Server der angelegte Tunnel läuft. Mehr zum Thema Metriken findest du unter Metriken mit Grafana und Prometheus.

Wenn du für dich entschieden hast Cloudflare zu nutzen, geht es nun los mit dem Anlegen deines Benutzeraccounts. Dazu rufst du die Startseite von Cloudflare auf und legst über „Registrieren“ einen neuen Account mit dem kostenlosen „Free“-Plan an.

Vorbereitung

Repository

Für die Ablage der Quellen für traefik und cloudflared kannst du dir ein weiteres Repository in Gitea anlegen, wenn du es in deiner Umgebung eingerichtet hast.

Ich verwende für die nachfolgende Abschnitte folgende Verzeichnisstruktur in einem Repository dmz.

Top-Level-Domain zu Cloudflare übertragen

Nachdem du die Registrierung abgeschlossen und dich mit deinem User angemeldet hast, registriert du in einem ersten Schritt deine Domain bei Cloudflare über „Domäne hinzufügen“.

Im nächsten Schritt gibst du anstelle des Platzhalters www.meine-domain.de deine Top-Level-Domain ein und klickst auf „Weiter“. Die empfohlene Einstellung zum Suchen nach DNS-Einträgen kannst du so belassen.

Cloudflare ermittelt daraufhin in kurzer Zeit die Daten und insb. die DNS-Einträge deiner Domain und fragt dich anschließend nach dem Plan für deine Domain. Für die hier beschriebenen Belange ist der Free-Plan ausreichend, daher wählst du diesen Plan aus und klickst

Nach etwas Bedenkzeit präsentiert dir Cloudflare die ermittelten DNS-Einträge zur Prüfung. Die Einstellungen kannst du ohne Änderungen mit einem Klick auf „Weiter zur Aktivierung“ übernehmen.

Im letzten Schritt zeigt dir Cloudflare welche Nameserver du in den DNS-Records deiner Domain eintragen musst, damit die Domain zukünftig über Cloudflare aufgerufen werden kann.

Mit einem Klick auf „Weiter“ schließt du die Einrichtung ab und Cloudflare zeigt dir einen Überblick an, in dem du die obigen Informationen zu den Nameservern erneut findest.

Jetzt ist es an der Zeit die Nameserver deiner Domain zu ändern. Cloudflare prüft zyklisch, ob das der Fall ist. Die Änderung der Nameserver wird u.U. erst nach 24h wirksam. Du kannst es auch manuell prüfen über den entsprechenden Link „Nameserver jetzt überprüfen“ unten auf der Überblicksseite.

Wenn die Nameserver erfolgreich geändert wurden, erscheint deine Domain als „Aktiv“ in der Domain-Übersicht in Cloudflare.

Du solltest nach Update der Nameserver die DNS-Einstellungen in Cloudflare nochmal prüfen und ggf. die zuvor erkannten Nameserver löschen (vgl. die beiden Zeilen in der Abbildung „Ermittelte DNS-Einträge„, die mit NS beginnen).

Änderung der Nameserver für deine Domain

Die Änderung der Nameserver ist von Anbieter zu Anbieter unterschiedlich. Die obigen Links „Anbieterspezifische Anweisungen“ enthalten leider nur allgemeine Informationen. Daher hier zwei Beispiele für Strato und Hostinger. Bei anderen Hosting-Anbietern ist das Vorgehen ähnlich.

Strato

Wenn du dich mit deinem Account bei Strato angemedelt hast, navigierst du zur Domainverwaltung und klickst bei der verwendeten Domain auf das kleine Rädchen oben rechts. Damit gelangst du in die Domaineinstellungen.

In den Domaineinstellungen wählst du in der ersten Zeile „NS-Record“ rechts den Link „verwalten“ und gelangst zu den Einstellungen der Nameserver. Hier trägst du nun die o.g. Nameserver von Cloudflare ein.

Hostinger

Nach deiner Anmeldung bei Hostinger wählst du für die betroffene Domain die Schaltfläche „Verwalten“ aus und gelangst zu den Details deiner Domain.

In der Ansicht der Domaindetails gelangst du über die Schaltfläche „Bearbeiten“ zur Änderung der Nameserver.

Cloudflare-Tunnel anlegen

Im nächsten Schritt legst du einen sog. Tunnel an, der die Verbindung von Cloudflare zu deiner Umgebung herstellt. Du musst dafür in deiner Firewall (FRITZ!Box) keine Ports freigeben, da der Endpunkt des Tunnel später der Docker-Container von cloudflared sein wird.

Im Dashboard von Cloudflare wählst du zunächst den Punkt „Zero Trust“, womit du in den gleichnamigen Bereich wechselst.

Im Zero Trust-Überblick kommst du mit Auswahl des Punktes „Networks| Tunnels“ in die Übersicht deiner existierenden Tunnel mit ihrem Status. Hier kannst über den Punkt „Neuen Tunnel erstellen“ genau das tun.

Das Anlegen eines neuen Tunnel startest du mit einem Klick auf „Tunnel erstellen“.

Im nächsten Schritt wählst du die Option „Cloudflared“ als Tunneltyp.

Anschließend vergibst du für deinen Tunnel einen beliebigen Namen. Ich habe der Einfachheit halber den Tunnel „mein_tunnel“ genannt. Mit „Tunnel speichern“ kommst du auf die nächste Seite zur Auswahl des Connectors.

Mit der Auswahl von „Docker“ erhälst du im Bereich „Connector installieren und ausführen“ ein docker-Kommando, mit dem du cloudflared in einem Docker-Container als Endpunkt für den Tunnel starten kannst. Dieses Kommando kopierst du dir einfach mit der kleinen Schaltfläche rechts in der Zeile. Du wirst später daraus das Tunnel-Token benötigen: die Zeichenkette hinter --token.

Über die Schaltfläche „Weiter“ kommst du zum Routing für deinen Tunnel.

Beim Routing des Tunnels geht es um die Definition einer Subdomain, über die du später einen Docker-Container aus dem Internet aufrufen kannst. Als Vorgriff auf den Abschnitt Nutzung gibst du hier als Subdomain „werbinich“ ein und wählst deine Top-Level-Domain aus. Die weiteren Angaben übernimmst du wie dargestellt.

Der Aufruf aus dem Internet wird über https erfolgen, der Empfänger des Aufrufs wird ein traefik-Container mit dem Namen traefik-tutorial sein. traefik installieren wir als Reverse Proxy für die Verteilung der Aufrufe aus dem Internet über Subdomains an den richtigen Docker-Container. Dazu später mehr im Kapitel Nutzung.

Wichtig sind außerdem die Angaben des Ursprungsservers für TLS: das ist die komplette URL der Subdomain, also werbinich.meine-domain.de. Zusätzlich schaltest du die HTTPS2-Verbindung ein.

Mit „Tunnel speichern“ schließt du die Erstellung des Tunnels ab und gelangst wieder zurück in die Übersicht deiner Tunnel, in der nun der gerade angelegte Tunnel „mein-tunnel“ als inaktiv aufgelistet wird.

Damit sind die notwendigen Voraussetzungen erledigt und es geht an die Installation der Docker-Container für cloudflared und traefik.

TLS-Zertifikate

Wenn deine Domain bei Cloudflare erfolgreich aktiviert wurde, kannst du von Cloudflare das sog. Ursprungszertifikat herunterladen, das auf deine Domain ausgestellt ist. Dieses Zertifikat wird von Traefik verwendet, um die HTTPS-Verbindung abzusichern.

Für den Download des Zertifikats meldest du dich bei Cloudflare an, falls noch nicht geschehen, und klickst auf der Startseite auf deine aktivierte Domain. Anschließend wählst du im Navigationsmenü unter „SSL/TLS“ den Punkt „Ursprungsserver“.

Auf nachfolgenden Seite siehst du die Liste der Domains, für die du bereits Ursprungszertifikate erstellt hast. Die Liste sollte leer sein. Über die Schaltfläche „Zertifikat erstellen“ startest du den Prozess zur Neuerstellung.

Im ersten Schritt der Zertifikatserstellung wirst du nach der Schlüssellänge und der Gültigkeit gefragt. In der Zeile der URL sollte deine Domain zweimal erscheinen: als mein-domain.de und *.meine-domain.de. Der zweite Eintrag sorgt dafür, dass sämtliche Subdomains ebenfalls das Zertifikat für die HTTPS-Kommunikation nutzen können. Die Einstellungen auf dieser Seite kannst du wie vorgeschlagen mit einem Klick auf „Erstellen“ benutzen.

Nach der Erstellung werden dir für dein Zertifikat zwei Downloads angeboten: das Zertifikat an sich und den dazugehörigen private Schlüssel. Beides liegt als Hash-String vor, du kannst diese jeweils mit „Zum Kopieren klicken“ in die Zwischenablage kopieren und von dort in eine Textdatei einfügen. Für das Zertifikat belässt du es bei PEM als Schlüsselformat und speicherst die Datei als dein-zertifikat.pem. Mit dem privaten Schlüssel verfährst analog und speicherst ihn als dein-zertifikat.key. Diese beiden Dateinamen werden weiter unten in der dynamischen Konfiguration von Traefik weiter unten verwendet. Wenn du die Dateinamen änderst, musst du sie auch in der Konfigurationsdatei anpassen.

WICHTIGER HINWEIS
Den privaten Schlüssel musst du im Erstellprozess sichern! Cloudflare speichert diesen Schlüssel nicht, sodass du ihn auch nicht erneut abrufen kannst. Wenn du den privaten Schlüssel verlegst, musst du dein bisheriges Zertifikat widerrufen, ein neues erstellen, dieses gem. der Beschreibung unten ins richtige Verzeichnis deiner Datenablage für Docker kopieren und anschließend Traefik bzw. den angelegten Stack in Portainer neu starten.

Wenn du beide Dateien erstellt hast, beendest du die Zertifikatserstellung mit einem Klick auf „OK“.

Installation

Etwas Networking vorweg

In den vorangegangenen Kapiteln habe ich es so gehalten, dass ich für jeden Docker-Stack ein eigenes Netzwerk innerhalb der Docker-Umgebung erstellt habe. Dieses Konzept setze ich mit cloudflared und traefik fort.

Es wird ein Docker-Netzwerk nw-dekayone-clf geben für die Verbindung für den Cloudflare-Tunnel zum Reverse Proxy und weiteres nw-dekayone-dmz für die Verbindung vom Reverse Proxy zu den Docker-Containern, die über das Internet erreichbar sind. Diese beiden Netzwerke legst du wie gewohnt mit Portainer an bevor du den Stack für Cloudflare und Traefik startest. Die Netzwerknamen kannst du deinen Bedürfnissen anpassen. Du musst dann darauf achten, dass du diese Netzwerknamen in deiner docker-compose.yml verwendest.

cloudflared und traefik

Für cloudflared und traefik legst du eine docker-compose.yml an, das später als Stack in Portainer gestartet wird.

Nachdem du die Inhalte der Dateien unten kopiert und in die jeweiligen Dateien im VSC eingefügt hast, kannst du sie deinen eigenen Bedürfnissen anpassen.

In der Datei docker-compose.yml legst du sowohl einen Service für cloudflared als auch für traefik als Reverse-Proxy an. In der Datei musst du folgende Zeilen an deine Bedürfnisse anpassen:

Bei der Anlage des Tunnels hast du dir das docker-Kommando zum Starten von cloudflared kopiert. Daraus benötigst du wie ober bereits erwähnt dein Tunnel-Token. Dieses ergänzt du in Zeile 8 der .env-Datei. Und nicht vergessen in Zeile 5 der .env-Datei den Link auf deine Datenablage einzutragen.

Darüber hinaus benötigt traefik eine statische und eine dynamische Konfiguration, traefik.yml bzw. dynamic_conf.yml. Wie du bereits vermutest wird die statische Konfiguration nur beim Start von traefik eingelesen, wohingegen Änderungen an der dynamischen Konfiguration zyklisch geprüft werden.

  • Zeile 10
    Hier steht der Netzwerkname für die Verbindung zwischen cloudflared und traefik.
  • Zeile 14
    Diese Zeile sorgt für die Verknüpfung des Routings der einzelnen Subdomains in Cloudflare und Traefik. Du musst hier den URL-Anteil des Dienstes aus dem Routing für deine Subdomain eintragen. Wenn du den Namen nicht verändert hast, ist die Bezeichnung traefik-tutorial.
  • Zeilen 19-22
    Hier müssen die Verzeichnisnamen mit deiner Dateiablage zusammen passen. Eine Änderung ist nur notwendig, wenn du die Verzeichnisstruktur verändert hast.
  • Zeilen 26-27
    Der Service traefik steht mit einem Bein im selben Netzwerk wie cloudflared. Das zweite Netzwerk sorgt für die Verbindung zu den Docker-Containern.

In der dynamischen Konfiguration dynamic_conf.yml sorgen die Zeilen 9 und 10 sowie 12 und 13 dafür, dass die zuvor von Cloudflare heruntergeladenen Zertifikatsdateien in den Zertifikatsspeicher von traefik aufgenommen und für die TLS-Verbindung genutzt werden. Hier musst du nur etwas ändern, wenn du ein andere Verzeichnisstruktur verwendest bzw. deine Zertifikatsdateien anders benannt hast.

In der statischen Konfiguration traefik.yml sorgen die Zeilen 5 und 6 dafür, dass das Dashboard von Traefik verwendet werden soll. Dazu später mehr im Abschnitt Nutzung. Durch die Zeilen 11 und 15 werden die beiden angegebenen Log-Dateien im oben angelegten logs-Verzeichnis abgelegt, sodass du darauf jederzeit in deiner Datenablage zugreifen kannst. Mit den Zeilen 19-21 wird ausschließlich eine HTTPS-Verbindung zugelassen. Und schließlich sorgt der Abschnitt providers ab Zeile 24 einerseits dafür, dass neue publizierte Docker-Container erkannt und anhand der eingetragenen Label zu traefik hinzugefügt werden (siehe dazu weiter unten im Abschnitt Nutzung). Andererseits wird hier ein Watchdog auf die dynamische Konfigurationsdatei dynamic_conf.yml definiert.

docker-compose.yml für cloudflared und traefik
services:
  cloudflare:
    image: cloudflare/cloudflared:latest
    container_name: cloudflare-tutorial
    command: tunnel run  
    environment:
      - TUNNEL_TOKEN=${TUNNEL_TOKEN}
    restart: unless-stopped
    networks:
      - nw-dekayone-clf

  traefik:
    image: traefik:3.2
    container_name: traefik-tutorial
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/localtime:/etc/localtime:ro
      - ${DATA_ROOT}/dmz/config/traefik.yml:/traefik.yml:ro
      - ${DATA_ROOT}/dmz/config/dynamic_conf.yml:/dynamic_conf.yml:ro
      - ${DATA_ROOT}/dmz/certificates/origin-certificates:/origin-certificates:ro
      - ${DATA_ROOT}/dmz/logs:/logs
    networks:
      - nw-dekayone-clf
      - nw-dekayone-dmz

networks:
  nw-dekayone-clf:    # network to cloudflare
    external: true
  nw-dekayone-dmz:    # internal network for attaching exposed services
    external: true

.env für cloudflared und traefik
# timezone
TIMEZONE=Europe/Berlin

# mountpoint of persistent data storage on NAS
DATA_ROOT=dein_datenablage_share

# cloudflare
TUNNEL_TOKEN=dein_tunnel_token

dynamic_conf.yml
# Dynamic configuration file of traefik
# This file is watched by the provider 'docker' which is configured within
# traefik's static configuration file 'traefik.yml'

# Add TLS-certificates of cloudflare tunnel and use them as default
tls:
  stores:
    default:
      defaultCertificate:
        certFile: /origin-certificates/dein-zertifikat.pem
        keyFile: /origin-certificates/dein-zertifikat.key 
  certificates:
    - certFile: /origin-certificates/dein-zertifikat.pem
      keyFile: /origin-certificates/dein-zertifikat.key
traefik.yml
# Static configuration file of traefik

# use dashboard, access configured in dynanmic_conf.yml
api:
  dashboard: true
  insecure: true

# configure logging
log:
  level: DEBUG
  filePath: "/logs/traefik.log"
  maxSize: 10
  maxBackups: 3
accessLog:
  filePath: "/logs/access.log"
  bufferingSize: 100

# only HTTPS-entrypoint
entryPoints:
  https:
    address: ":443"

# the providers
providers:
  # Definition of provider 'docker' with dynamic configuration file 'dynamic_conf.yml'
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    watch: true
  file:
    filename: dynamic_conf.yml
    watch: true
    

Nachdem du alle Änderungen vorgenommen und gespeichert hast, wechselt du in VSC in die Quellcoderverwaltung. Dort beförderst du alle geänderten Dateien mit einem „Commit und Push“ in das Repository dmz. Wenn du an dieser Stelle nicht möchtest, dass die Zertifikatsdateien mit im Repository landen, musst du sie vom Commit ausschließen!

Bevor es nun an das Anlegen der Netzwerke und des Stacks für cloudflared und traefik geht ist etwas manuelle Arbeit notwendig, denn die beiden Zertifíkatsdateien sowie die beiden Konfigurationsdateien traefik.yml und dynamic_conf.yml müssen noch in den richtigen Verzeichnissen in deiner Datenablage landen.

Ich verwende in den nachfolgenden Schritten in der Konsole deines Pi stellvertretend ${DATA_ROOT} für das Hauptverzeichnis, dass auch in allen docker-compose.yml in den vorangegangenen Kapiteln verwendet wurde. Du musst diesen Ausdruck durch dein Verzeichnis ersetzen, das du beim Einrichten der Datenablage angelegt hast. Der Einfachheit halber kannst du dir dafür auch eine Umgebungsvariable anlegen, falls du das bei der Einrichtung der Datenablage nicht getan hast. Falls du die Verzeichnisse in docker.compose.yml verändert hast, musst du die Verzeichnisse in den nachfolgenden Kommandos verwenden, sodass die Dateien an den entsprechenden Stellen im Docker-Container verwendet werden können.

export DATA_ROOT=dein_datenablage_share

Anschließend legst du dir in deinem Docker-Share mit mkdir ein neues Verzeichnis dmz und darin die Unterverzeichnisse

  • config
  • logs
  • certificates mit weiterem Unterverzeichnis origin-certificates

Die Option -p bei mkdir bewirkt, dass alle Verzeichnisse im angegebenen Pfad erstellt werden, sofern sie noch nicht vorhanden sind.

mkdir -p ${DATA_ROOT}/dmz/config
mkdir -p ${DATA_ROOT}/dmz/logs
mkdir -p ${DATA_ROOT}/dmz/certificates/origin-certificates

Anschließend kopierst du die notwendigen Dateien in die Verzeichnisse.

  • dmz/config
    Hier landen die Dateien traefik.yml und dynamic_conf.yml
  • certificates/origin-certificates
    In dieser Verzeichnis kopierst du die .pem– und .key-Datei, die du von Cloudflare heruntergeladen hast.

In der Konsole des Pi legst du mit nano die entsprechenden Dateien an und kopierst die Inhalte in den Editor (Umschalt+Einfg). Mit Strg+X beendest du nano und beantwortest die Nachfrage zum Speichern mit J oder Y.

nano ${DATA_ROOT}/dmz/config/traefik.yml
nano ${DATA_ROOT}/dmz/config/dynamic_conf.yml
nano ${DATA_ROOT}/dmz/certificates/origin-certificates/dein-zertifikat.pem
nano ${DATA_ROOT}/dmz/certificates/origin-certificates/dein-zertifikat.key

Alternativ kannst du die Dateien z.B. auch von einem Windows-Rechner mit WinSCP auf deinen Pi übertragen. Oder du nutzt das im Windows-Explorer eingebundene Share zu deiner Datenablage und kopierst darüber die Dateien in die entsprechenden Verzeichnisse.

Ein kleiner Tipp: falls im laufenden Betrieb etwas klemmen sollte, liegt es höchstwahrscheinlich an falschen Berechtigungen auf ein Verzeichnis oder eine Datei. Dies kannst du auf der Konsole mit ls -la anzeigen lassen und mit den Kommandos chown bzw. chmod ändern. Siehe dazu z.B. unter shellbefehle.de

Nach diesem kleinen Ausflug auf die Konsole kannst du in Portainer einen neuen Stack dmz für Cloudflare und Traefik anlegen. Als Quelle benutzt du in diesem Fall das Repository dmz mit dem Compose Path build/clouflare/docker-compose.yml.

Nach dem erfolgreichen Start des Stacks siehst du in den Details dazu zwei laufende Docker-Container in einem grünen „running“-Status: cloudflare-tutorial und traefik-tutorial.

In Cloudflare kannst nun sehen, dass dein Tunnel fehlerfrei funktioniert. Auf diesen Grundlagen kannst du deine Services über Subdomains aus dem Internet aufrufen. Wie das funktioniert beschreibe ich im folgenden Abschnitt Nutzung anhand einiger Beispiele.

Nutzung

Grundsätzliches

Die über Traefik erreichbaren Docker-Container können auf zwei verschiedene Arten angebunden werden. Du kannst einerseits die oben bereits angelegte dynamische Konfiguration erweitern und dort die Services definieren. Oder du steuerst die Konfiguration über Labels in den einzelnen docker-compose.yml der Docker-Container. Beide Varianten sind in der Traefik-Dokumentation beschrieben.

Ich habe mich für die zweite Variante entschieden und die notwendigen Labels in den docker-compose.yml definiert. Das hat aus meiner Sicht den Vorteil, dass man bei Änderungen am Docker-Container auch gleich immer die Traefik-Einstellungen mit dabei hat. So muss man keine zwei Dateien pflegen. Ich werde daher im Folgenden die Label-Variante beschreiben.

Du kannst dir folgendes Template für die notwendigen Traefik-Label zurechtlegen, das du in deine docker-compose.yml für die Services angibst, die über eine eigene Subdomain aus dem Internet erreichbar sein sollen:

    labels:
      - traefik.enable=true
      - traefik.http.routers.<service_name>.rule=Host(`subdomain.meine-domain.de`)
      - treafik.http.routers.<service_name>.entrypoints=https
      - traefik.http.routers.<service_name>.tls=true
      - traefik.http.routers.<service_name>.service=<service_name>
      - traefik.http.services.<service_name>.loadbalancer.server.port=<container_port>

Wie funktioniert das ganze?

Ich habe es mir zur Gewohnheit gemacht alle Services mit einem eindeutigen Container-Namen zu versehen, die über eine eigene Subdomain aus dem Internet erreichbar sein sollen. Dafür sorgt in einem docker-compose.yml die Verwendung der Option container_name: <service_name>. Mit dem vergebenen Namen ersetzt du im obigen Template den Platzhalter <service_name>.

Den Platzhalter <container_port> ersetzt du mit dem Port, den der entsprechende Container intern verwendet. Als Merker: das ist bei der Portangabe im docker-compose.yml die Angabe rechts vom Doppelpunkt. Wenn keine Ports angegeben sind, verwendet der Docker-Container die Standard-Ports, die üblicherweise in der Dokumentation zum jeweiligen Docker-Container angegeben sind

Den Text subdomain.meine-domain.de ersetzt du die Subdomain, über die du deinen Service erreichen möchtest. Wichtig ist, dass du hier die dargestellten Anführungszeichen verwendest.

Durch die obigen Labels legt Traefik einen sog. Router an, der die Verbindung von Subdomain zu deinem Service herstellt. Dafür gibst du im Label-Namen den Servicenamen an. Die generelle Nutzung von HTTPS und TLS wird über die Labels [..].entrypoints=https und [..].tls=true konfiguriert. Zum Schluss benötigen wir für die Angabe des Container-Ports noch einen Service in Traefik sowie die Port-Angabe selbst. Das wird mit den letzten beiden Label erledigt.

Ein erster Test mit whoami

Für einen ersten Test hast du bereits bei der Erstellung deines Tunnels die Subdomain werbinich für deine Domain angelegt. Diese Subdomain verwenden wir nun, um einen whoami-Dienst aufrufen zu können.

Zu Beginn des Kapitels hast du bereits ein Verzeichnis für whoami angelegt. In die darin angelegte docker-compose.yml kopierst du den nachfolgenden Inhalt.

docker-compose.yml für whoami
services:
  whoami:
    image: traefik/whoami
    container_name: whoami-tutorial
    restart: unless-stopped
    labels:
      - traefik.enable=true
      - traefik.http.routers.whoami-tutorial.rule=Host(`werbinich.meine-domain.de`)
      - treafik.http.routers.whoami-tutorial.entrypoints=https
      - traefik.http.routers.whwhoami-tutorialami.tls=true
      - traefik.http.routers.whoami-tutorial.service=whoami-tutorial
      - traefik.http.services.whoami-tutorial.loadbalancer.server.port=80
    networks:
      - nw-dekayone-dmz

networks:
  nw-dekayone-dmz:
    external: true

Gemäß des obigen Templates für die Traefik-Label sind folgende Ersetzungen vorgenommen:

  • <service_name> = whoami-tutorial
  • <container-port> = 80, in diesem Fall der Standard-Port

In Zeile 10 musst du deine Subdomain eintragen.

Der Container ist über Angabe des Netzwerk nw-dekayone-dmz von Traefik erreichbar.

Hier gilt wie immer: wenn du die Namen deinen Bedürfnissen angepasst hast, dann musst du diese Änderungen auch hier vornehmen!

Wenn alles gespeichert und per „Commit und Push“ ins Repository dmz befördert hast, kannst du in Portainer einen neuen Stack whoami anlegen. Als Compose Path verwendest du build/whoami/docker-compose.yml. Anschließend startest du den Stack und findest nach kurzer Zeit den laufenden Container in den Stack-Details.

Wenn neben whoami auch der Stack für Cloudflare und Traefik läuft, wird es jetzt spannend. Du kannst in deinem Internet-Browser die Adresse werbinich.meine-domain.de eingeben und landest bei deinem whoami-Container, der ein paar Informationen im Browser ausgibt.

Traefik-Dashboard

Traefik bietet ein Dashboard an, in dem es die angelegten Router, Services usw. anzeigt. In diesem Abschnitt zeige ich die, wie du dieses Dashboard aus dem Internet über eine eigene Subdomain aufrufst, abgesichert mit einer BasicAuth.

Als erstes kümmern wir uns um die neue Subdomain. Dafür meldest du dich bei Cloudflare an, wechselt zu Zero Trust und navigierst dort zu deiner Tunnelübersicht. Dort wählst du im Menü rechts den Punkt „Konfigurieren“ für deinen Tunnel aus. Dabei ist der Status deines Tunnels egal.

Für deinen Tunnel kannst du nun im Bereich „Öffentlicher Hostname“ eine neue Subdomain für das Traefik-Dashboard anlegen.

Analog zum Tunnelrouting für whoami weiter oben vergibst du nun einen Namen für deine Subdomain und gibst folgenden Informationen bei den zusätzlichen Anwendungseinstellungen für TLS an:

  • Name des Ursprungsservers = die vollständige URL deiner Subdomain, hier: dashboard.meine-domain.de
  • Option HTTP2-Verbindung aktivieren

Mit einem Klick auf „Hostname speichern“ wird deine neue Subdomain angelegt und du siehst sie in der Liste der öffentlichen Hostnamen.

Zusätzlich wird ein DNS-Eintrag für deine Subdomain erzeugt. Diese siehst du im Cloudflare-Dashboard, wenn du auf deinen Domainnamen klickst und dann in der Navigation zuerst „DNS“ und dann „Einträge“ aufrufst. In der Liste deiner DNS-Einträge taucht „dashboard“ als CNAME-Eintrag auf.

Damit ist die neue Subdomain angelegt, jetzt folgt die Traefik-Konfiguration für den Aufruf des Dashboards über die URL dashboard.meine-domain.de

Über die statische Traefik-Konfiguration haben wir bereits eingestellt, dass Traefik das Dashboard anzeigen soll. Jetzt ergänzen wir in der docker-compose.yml die notwendigen Label für den Aufruf gem. des obigen Templates und ergänzen eine Authentifizierung mit Username und Passwort (BasichAuth) für den Aufruf des Dashboard.

Diese Ergänzung findest du unten im docker-compose.yml in den Zeilen 23-35. Da wir auf Traefik-interne Services zugreifen, wird ein Abschnitt mit <service_name>=dashboard (siehe traefik.http.routers.dashboard...) und ein weiterer mit <service_name>=api (siehe traefik.http.routers.api...) eingefügt. Und weil es keine Weiterleitung an einen anderen Docker-Container gibt, fehlt der Eintrag für den Port.

In den Zeilen 26 und 30 musst du deine Domain eintragen. Wichtig ist dabei, dass die angegebenen Anführungsstriche verwendet werden!

Für die Authentifizierung mit BasicAuth sorgen schließlich die Zeilen 28, 32 und 34. Die Authentifizierung wird als sog. Middleware für einen Router abgebildet. In Zeile 28 wird diese mit dem Namen traefikauth für den Service dashboard festgelegt, in Zeile 32 für den Service api.

In Zeile 34 wird für traefikauth der Benutzername und das dazugehörige Passwort in der Form username:password-hash definiert. Den Parameter password-hash kannst du mit dem Tool htpasswd auf der Konsole deines Pi erstellen.

htpasswd gehört zum Paket apache2-utils, das du wahrscheinlich auf deinem Pi noch installieren musst. Das erledigst du mit

sudo apt-get update
sudo apt-get install apache2-utils

Danach kannst du mit folgendem Kommando einen Password-Hash erzeugen, in diesem Fall für den Nutzername test mit dem Passwort dk1tutorial. Diesen Nutzer verwende ich als Beispiel für den Zugriff auf das Traefik-Dashboard und du solltest ihn unbedingt ändern und in dein docker-compose.yml aufnehmen.

htpasswd -nb test dk1tutorial
docker-compose.yml mit Traefik-Dashboard
services:
  cloudflare:
    image: cloudflare/cloudflared:latest
    container_name: cloudflare-tutorial
    command: tunnel run  
    environment:
      - TUNNEL_TOKEN=${TUNNEL_TOKEN}
    restart: unless-stopped
    networks:
      - nw-dekayone-clf

  traefik:
    image: traefik:3.2
    container_name: traefik-tutorial
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /etc/localtime:/etc/localtime:ro
      - ${DATA_ROOT}/dmz/config/traefik.yml:/traefik.yml:ro
      - ${DATA_ROOT}/dmz/config/dynamic_conf.yml:/dynamic_conf.yml:ro
      - ${DATA_ROOT}/dmz/certificates/origin-certificates:/origin-certificates:ro
      - ${DATA_ROOT}/dmz/logs:/logs
    labels:
      - traefik.enable=true
      # Traefik's dashoard
      - traefik.http.routers.dashboard.rule=Host(`dashboard.meine-domain.de`)
      - traefik.http.routers.dashboard.service=dashboard@internal
      - traefik.http.routers.dashboard.middlewares=traefikauth
      - traefik.http.routers.dashboard.tls=true
      - traefik.http.routers.api.rule=Host(`dashboard.meine-domain.de`) && PathPrefix(`/api`)
      - traefik.http.routers.api.service=api@internal
      - traefik.http.routers.api.middlewares=traefikauth
      - traefik.http.routers.api.tls=true
      - traefik.http.middlewares.traefikauth.basicauth.users=test:$apr1$ztPz9Iln$mXWxOyWBFx4iN225A6ma2/
    networks:
      - nw-dekayone-clf
      - nw-dekayone-dmz

networks:
  nw-dekayone-clf:    # network to cloudflare
    external: true
  nw-dekayone-dmz:    # internal network for attaching exposed services
    external: true

Wenn du die Änderungen in Visual Code Studio gespeichert hast und wie zuvor beschrieben ein Gitea-Repository eingerichtet hast, aktualisierst du mit einem „Commit und Push“ die Dateien im Repository. Jetzt kannst du in Portainer den Stack dmz aufrufen und über „Pull and redeploy“ deinen Stack mit dem gerade aktualisiertem docker-compose.yml neu starten.

Vor dem Redeploy musst du eine Sicherheitsabfrage mit einem Klick auf „Update“ bestätigen. Hier hast du neben dem eigentlichen Redeploy auf Basis der docker-compose.yml die Möglichkeit, den Container an sich zu aktualisieren. Dazu aktivierst du die Option „Re-pull image and redeploy“. Portainer prüft daraufhin, ob Aktualisierungen für die Docker-Images im docker-compose.yml vorliegen, lädt diese herunter und verwendet sie für das Redeploy.

Im Internet Browser landest du bei Eingabe von https://dashboard.mein-domain.de auf dem Traefik-Dashboard. Bevor es im Browser angezeigt wird, musst du für den Zugriff den im docker-compose.yml angegebenen Nutzer und Passwort für die BasicAuth eingeben. Danach siehst du eine ähnliche Darstellung wie die folgende.

Du kannst im Traefik-Dashboard kannst du nun auf den Link „Explore“ bei Routers, Services und Middlewares klicken und siehst in weiteren Seiten die Details dazu. Ganz interessant finde ich die Ansicht für die Router. Dort öffnet sich eine Auflistung aller definierten Services.

Hier solltest du einen Eintrag „Host(`werbinich.meine-domain.de`) sehen und anklicken können. Daraufhin zeigt Traefik eine kleine grafische Übersicht zum Zusammenhang zwischen Entrypoint, Router und Service sowie einige Details zum Router an.

Paperless

Die Vorgehensweise in den beiden vorangegangenen Abschnitten können wir nun adaptieren, um Paperless als weiteren Dienst über eine Subdomain über das Internet zugänglich zu machen.

Dazu legst du wie beim Tunnelrouting für whoami bzw. des Traefik-Dashboards weiter oben eine neue Subdomain (z.B. paperless) an und gibst folgenden Informationen bei den zusätzlichen Anwendungseinstellungen für TLS an:

  • Name des Ursprungsservers = die vollständige URL deiner Subdomain, hier: paperless.meine-domain.de
  • Option HTTP2-Verbindung aktivieren

Mit einem Klick auf „Hostname speichern“ wird deine neue Subdomain für Paperless samt Eintrag in der DNS-Liste gespeichert.

Nun geht es daran die docker-compose.yml und .env zu ergänzen. Dazu nutzen wir wieder obiges Template für die Traefik-Label. Folgende Ergänzungen musst du in der docker-compose.yml vornehmen:

  • Zeile 51
    Hier musst du zusätzlich das Docker-Netzwerk ergänzen, das Traefik mit dem Docker-Container von Paperless verbindet. Hier ist es das Netzwerk nw-dekayone-dmz gem. dieser Darstellung. Dieses Netzwerk musst du nur beim Applikationsservice paperless ergänzen.
  • Zeilen 53-59
    Hier ergänzt du den Block mit den Traefik-Label für Paperless. Als <service_name> verwendest du plngx-app, der Host ist die URL der zuvor angelegten Subdomian und der Container-Port in diesem Fall 8000.
  • Zeilen 64-65
    Die beiden Zeilen ergänzen das Netzwerk nw-dekayone-dmz als externes Netzwerk. Falls du dieses Netzwerk anders benannt hast, musst es hier und in Zeile 51 eintragen.

In der .env musst du in Zeile 41 die URL angeben, über die Paperless erreichbar ist. Hier ist es die URL paperless.meine-domain.de bzw. diejenige, die du zuvor angelegt hast.

docker-compose.yml paperless-ngx
services:
  broker:
    image: docker.io/library/redis:7
    restart: unless-stopped
    container_name: plngx-redis
    volumes:
      - ${DATA_ROOT}/paperless/redis/data:/data
    ports:
      - 6379:6379
    networks:
      - nw-dekayone-plngx
 
  db:
    image: docker.io/library/mariadb:10
    container_name: plngx-db 
    restart: unless-stopped 
    volumes:
      - ${DATA_ROOT}/paperless/db:/var/lib/mysql 
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ADMIN_PASSWORD}
      - MYSQL_DATABASE=${DB_DATABASE}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    networks:
      - nw-dekayone-plngx
       
  paperless:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    container_name: plngx-app 
    restart: unless-stopped
    depends_on:
      - db 
      - broker
    ports:
      - 8000:8000 
    volumes:
      - ${DATA_ROOT}/paperless/data:/usr/src/paperless/data
      - ${DATA_ROOT}/paperless/media:/usr/src/paperless/media
      - ${DATA_ROOT}/paperless/export:/usr/src/paperless/export
      - ${DATA_ROOT}/paperless/consume:/usr/src/paperless/consume
    environment:
      - PAPERLESS_REDIS=redis://broker:6379
      - PAPERLESS_DBENGINE=mariadb
      - PAPERLESS_DBHOST=db
      - PAPERLESS_DBUSER=${DB_USER}
      - PAPERLESS_DBPASS=${DB_PASSWORD}
      - PAPERLESS_DBPORT=3306
      - PAPERLESS_CONSUMER_POLLING=30    
    networks:
      - nw-dekayone-plngx
      - nw-dekayone-dmz
    labels:
      - traefik.enable=true
      - traefik.http.routers.plngx-app.rule=Host(`paperless.meine-domain.de`)
      - treafik.http.routers.plngx-app.entrypoints=https
      - traefik.http.routers.plngx-app.tls=true
      - traefik.http.routers.plngx-app.service=plngx-app
      - traefik.http.services.plngx-app.loadbalancer.server.port=8000
      - com.centurylinklabs.watchtower.enable=true
         
networks:
  nw-dekayone-plngx:
    external: true
  nw-dekayone-dmz:
    external: true
.env für paperles-ngx
# general timezone
TIMEZONE=Europe/Berlin

# mountpoint of persistent data storage on NAS
DATA_ROOT=dein_datenablage_share

# MYSQL settings
DB_ADMIN_PASSWORD=supersecretadminpassword
DB_PASSWORD=secretuserpassword
DB_DATABASE=paperless
DB_USER=paperless

# The UID and GID of the user used to run paperless in the container. Set this
# to your UID and GID on the host so that you have write access to the
# consumption directory.

USERMAP_UID=1002
USERMAP_GID=1000

# Additional languages to install for text recognition, separated by a
# whitespace. Note that this is
# different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines the
# language used for OCR.
# The container installs English, German, Italian, Spanish and French by
# default.
# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names&suite=buster
# for available languages.

PAPERLESS_OCR_LANGUAGES=deu

###############################################################################
# Paperless-specific settings
###############################################################################

# All settings defined in the paperless.conf.example can be used here. The
# Docker setup does not use the configuration file.
# A few commonly adjusted settings are provided below.
# This is required if you will be exposing Paperless-ngx on a public domain
# (if doing so please consider security measures such as reverse proxy)
PAPERLESS_URL=https://paperless.meine-domain.de
# Adjust this key if you plan to make paperless available publicly. It should
# be a very long sequence of random characters. You don't need to remember it.
PAPERLESS_SECRET_KEY=deinsuperlangersupergeheimertokenauszufaelligenzeichen
# Use this variable to set a timezone for the Paperless Docker containers. If not specified, defaults to UTC.

PAPERLESS_TIME_ZONE=Europe/Berlin

# The default language to use for OCR. Set this to the language most of your
# documents are written in.

PAPERLESS_OCR_LANGUAGE=deu

# Set if accessing paperless via a domain subpath e.g. https://domain.com/PATHPREFIX and using a reverse-proxy like traefik or nginx

#PAPERLESS_FORCE_SCRIPT_NAME=/PATHPREFIX
#PAPERLESS_STATIC_URL=/PATHPREFIX/static/ # trailing slash required
PAPERLESS_CONSUMER_POLLING=30

PAPERLESS_CONSUMER_ASN_BARCODE_PREFIX=ASN
PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE=true
PAPERLESS_CONSUMER_ENABLE_BARCODES=true
PAPERLESS_CONSUMER_BARCODE_SCANNER=ZXING

Nachdem du die Änderungen vorgenommen und diese in dein Repository gepusht hast, kannst du in Portainer den Stack für Paperless neu deployen. Anschließend kannst du auf deinen Paperless-Container über die URL paperless.meine-domain.de zugreifen.

Diese URL kannst du auch in den verschiedenen Apps auf deinem Mobilgeräten verwenden, die du in den verschiedenen App-Stores findest. Ich selber verwenden auf meinen iOS-Geräten die App Swift Paperless von Paul Gessinger.

WordPress

Auch für WordPress ist die Vorgehensweise analog zu dem vorangegangenem Abschnitt. Als ersten Schritt legst du eine weitere Subdomain in Zero Trust für deinen Tunnel an mit den Einstellungen zum Namen des Ursprungsservers und der Aktivierung der HTTP2-Option. Ich verwende im folgenden die Subdomain wordpress.meine-domain.de.

Damit deine WordPress über die URL wordpress.meine-domain.de erreichbar ist, musst du die folgenden Änderungen an der existierenden docker-compose.yml vornehmen. In der Datei .env sind keine Änderungen erforderlich.

  • Zeilen 32-34
    Über die Umgebungsvariable WORDPRESS_CONFIG_EXTRA wird die URL in den beiden define(...)-Zeilen gesetzt, über die deine Site erreichbar ist, hier wordpress.meine-domain.de.
    Über WORDPRESS_CONFIG_EXTRA kannst du PHP-Anweisungen wie die beiden define(...)-Zeilen an deine WordPress-Instanz übergeben. Die Anweisungen werden beim Starten deiner WordPress-Instanz einmalig ausgeführt (über wp-config.php im Verzeichnis html deiner WordPress-Instanz). Weitere Information dazu findest du im Abschnitt WordPress-Configuration in der Administrator-Dokumentation von WordPress.
  • Zeile 37
    Hier musst du zusätzlich das Docker-Netzwerk ergänzen, das Traefik mit dem Docker-Container von WordPress verbindet. Hier ist es das Netzwerk nw-dekayone-dmz gem. dieser Darstellung. Dieses Netzwerk musst du nur für den Service wp-app ergänzen.
  • Zeilen 40-45
    In diesen Zeilen findest du die Traefik-Label für WordPress, die du deinen Gegebenheiten anpassen musst. Diesem Beispiel folgend wird wp-app als <service_name>, wordpress.meine-domain.de als URL und 80 als <container_port> verwendet.
  • Zeilen 50-51
    Analog zum Paperless-Beispiel zuvor ergänzen diese beiden Zeilen das Netzwerk nw-dekayone-dmz als externes Netzwerk. Falls du dieses Netzwerk anders benannt hast, musst es hier und in Zeile 51 eintragen.
docker-compose.yml für WordPress
services:
  db:
    image: mariadb:10.5
    container_name: wp-db 
    restart: unless-stopped 
    volumes:
      - ${DATA_ROOT}/wordpress/db:/var/lib/mysql 
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ADMIN_PASSWORD}
      - MYSQL_DATABASE=${DB_DATABASE}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    networks:
      - nw-dekayone-wp2
       
  wordpress:
    image: wordpress:latest
    container_name: wp-app 
    restart: unless-stopped
    depends_on:
      - db 
    ports:
      - 8060:80 
    volumes:
      - ${DATA_ROOT}/wordpress/html:/var/www/html     # contains wp-content/plugins | themes | uploads
      - ${DATA_ROOT}/wordpress/config/upload.ini:/usr/local/etc/php/conf.d/upload.ini 
    environment:
      - WORDPRESS_DB_HOST=db:3306 
      - WORDPRESS_DB_USER=${DB_USER}
      - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}
      - WORDPRESS_DB_NAME=${DB_DATABASE}
      - WORDPRESS_CONFIG_EXTRA=
          define('WP_HOME','https://wordpress.meine-domain.de');
          define('WP_SITEURL','https://wordpress.meine-domain.de');
    networks:
      - nw-dekayone-wp2
      - nw-dekayone-dmz
    labels:
      - com.centurylinklabs.watchtower.enable=true
      - traefik.enable=true
      - traefik.http.routers.wp-app.rule=Host(`wordpress.meine-domain.de`)
      - treafik.http.routers.wp-app.entrypoints=https
      - traefik.http.routers.wp-app.tls=true
      - traefik.http.routers.wp-app.service=wp-app
      - traefik.http.services.wp-app.loadbalancer.server.port=80
 
networks:
  nw-dekayone-wp2:
    external: true
  nw-dekayone-dmz:
    external: true

Nachdem du alle notwendigen Anpassungen vorgenommen hast, kannst du diese mit einem „Commit und Push“ in das Repository wordpress befördern. Anschließend startest du den Stack für WordPress in Portainer über ein „Pull and redeploy“ neu. Danach ist deine Site in WordPress über die Subdomain wordpress.meine-domain.de aus dem Internet erreichbar. Das Dashboard von WordPress erreichst du über die URL wordpress.meine-domain.de/wp-admin.

Hier einige Punkte, die ich dir noch an Herz legen möchte:

  • Mit der Erreichbarkeit über das Internet können auch unliebsame Gäste auf deine Site zugreifen. Um hier einen gewissen Schutz einzurichten, gibt es einige WordPress-Plugins, die z.B. die Login-Seite von WordPress auf eine alternative URL umbiegen oder eine zweiten Faktor für die Anmeldung am Dashboard implementieren. Für deine Bedürfnisse geeignete Plugins findest du im Internet oder über die Suche auf der Plugin-Seite von WordPress.
  • Da die URL für WordPress über die Umgebungsvariablen eingestellt wird, kannst du diese URL nicht mehr in den Einstellungen von WordPress ändern. Die entsprechenden Eingabefelder sind deaktiviert. Falls du die URL ändern möchtest (oder musst), kannst du das in der docker-compose.yml (Zeilen 32-34 über die beiden define(...)-Anweisungen) vornehmen und den Stack mit den geänderten Einstellungen neu starten.
  • Ich habe die Erfahrung gemacht, dass Traefik nach Neustarts des WordPress-Stacks manchmal eine falsche IP-Adresse verwendet und damit das Routing zu WordPress nicht funktioniert. Die WordPress-Site ist dann nicht erreichbar. Hier schafft i.d.R. ein Neustart des Stacks für Cloudflare und Traefik Abhilfe.
  • Wenn du mehrere Website mit WordPress betreiben möchtest, bietet es den sog. Multisite-Betrieb an, in dem u.a. die installierten Plugins und Themes gemeinsam genutzt werden. Ich habe damit etwas herumgespielt, da ich zwei Websites mit WordPress betreibe. Allerdings habe ich für mich den Multisite-Betrieb nicht vernünftig zum Laufen bekommen und mich daher entschieden zwei separate WordPress-Instanzen zu nutzen.
    Wenn du das ebenfalls machen möchtest, kannst du die vorhandenen docker-compose.yml und .env wiederverwenden. Du musst dann darauf achten, dass du ein anderes Ablageverzeichnis, einen anderen Port und eine andere URL für die zweite Instanz verwendest, um das Routing zur zweiten Instanz in Traefik abbilden zu können. Der Nachteil: du musst deine Plugins und Themes usw. in beiden Instanzen installieren und aktualisieren.

Quellen und Links


Dieser Beitrag hat einen Kommentar

Schreibe einen Kommentar