Docker Services mit Traefik verwalten

Veröffentlicht in: , ,

Mit dem Reverse-Proxy Traefik lassen sich Docker-Container effizient verwalten und komfortabel im Browser aufrufen – ganz ohne manuelles Jonglieren mit Portnummern.

In diesem Beitrag richten wir eine lokale Testumgebung ein, die verschiedene Webprojekte umfasst: mehrere WordPress-Instanzen, phpMyAdmin, Joomla, Drupal, eine statische HTML Seiten und eine Landing-Page für das Projekt. Host-System ist Ubuntu 25.04.

Alle Dateien und Skripte des Projekts haben wir für Sie auf GitHub bereitgestellt.

GitHub. Projekt WebDev

Im vorherigen Beitrag haben wir bereits gezeigt, wie sich eine einfache WordPress-Testumgebung mit Docker aufsetzen lässt. Nun erweitern wir dieses Setup und machen es durch Traefik deutlich flexibler und übersichtlicher.

Projektstruktur

Alle Dienste werden in einem übergeordneten Projektverzeichnis namens WebDev organisiert. Für jeden Container gibt es einen eigenen Unterordner mit einer individuellen docker-compose.yaml. Ein zentrales Skript steuert den Start und Stopp aller Container gleichzeitig.

Das Projekt umfasst:

  • traefik – zentrale Reverse-Proxy-Konfiguration
  • wp1, wp2 – zwei eigenständige WordPress-Instanzen
  • drupal1 – Drupal mit PostgreSQL
  • joomla1 – Joomla mit MySQL
  • html – statische Website mit NGINX
  • pma – phpMyAdmin zur Datenbankverwaltung
  • landingpage – eine zentrale Startseite mit Links zu allen Projekten
  • README.md-Dateien – Dokumentation pro Container (optional)

Verzeichnisbaum:

WebDev/
├── drupal1/
│   ├── compose.yaml
│   └── README.md
├── html/
│   ├── compose.yaml
│   └── public/
│       └── index.html
├── joomla1/
│   ├── compose.yaml
│   └── README.md
├── landingpage/
│   ├── compose.yaml
│   ├── public/
│   │   ├── index.html
│   │   └── styles.css
│   └── README.md
├── pma/
│   ├── compose.yaml
│   └── README.md
├── traefik/
│   └── compose.yaml
├── wp1/
│   ├── compose.yaml
│   └── README.md
├── wp2/
│   ├── compose.yaml
│   └── README.md
├── start-all.sh
├── stop-all.sh
└── README.md

Container erstellen

Die einzelnen Unterordner enthalten jeweils ihre eigene Compose-Datei. Jedes Web-Projekt verwendet einen eigenen Datenbank-Container.

1. Traefik als Reverse-Proxy

Der traefik-Container ist die zentrale Schaltstelle. Er lauscht auf Port 80 (lokal begrenzt auf 127.0.0.1) und leitet Anfragen basierend auf der gewünschten Domain weiter.

Jeder Service registriert sich bei Traefik über Container-Labels, etwa:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.wp1.rule=Host(`wp1.localhost`)"
  - "traefik.http.routers.wp1.entrypoints=web"

Anhand diese Labels erkennt Traefik den Service, an den die Anfrage weitergeleitet werden soll. Ohne Traefik würde diese Adressierung durch Port-Nummern vorgenommen.

Wir erstellen den Container mit einer compose.yaml Datei:

# traefik compose local restricted

services:
  traefik:
    image: traefik:v3.4
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--api.dashboard=true"
      - "--api.insecure=true"    
      - "--log.level=INFO"
    ports:
      - "127.0.0.1:80:80"        # nur lokal zugänglich
      - "127.0.0.1:8080:8080"    # Dashboard nur lokal
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - webdev-net
    restart: unless-stopped

networks:
  webdev-net:
    external: true

Ein Dashboard unter http://localhost:8080 zeigt aktive Router, Services und Netzwerke. Für die Testumgebung ist eine Authentifizierung nicht erforderlich, im Produktiveinsatz aber unbedingt.

Die Ansicht im Dashboard lässt sich mit den üblichen Tastenkombinationen vergrößern und verkleinern, ohne dabei unbenutzbar zu werden.

Strg + Plus-Taste
Strg + Bindestrick (Minus)

2. Webprojekte (CMS und statisch)

Jedes CMS wird in einem eigenen Compose-Projekt betrieben:

  • WordPress (mit MariaDB)
  • Drupal (mit PostgreSQL)
  • Joomla (mit MySQL)
  • HTML-Seite (mit NGINX)

Alle sind über .localhost-Domains erreichbar, z. B.

wp1.localhostdrupal1.localhost

Beispiel für eine compose.yaml Datei:

# compose.yaml Example

services:
  wordpress1:
    image: wordpress
    environment:
      WORDPRESS_DB_HOST: db_wp1
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp1_data:/var/www/html
    networks:
      - webdev-net
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wp1.rule=Host(`wp1.localhost`)"
      - "traefik.http.routers.wp1.entrypoints=web"
    restart: unless-stopped

  db_wp1:
    image: mariadb
    container_name: wp1-db_wp1
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: examplepass
      MYSQL_ROOT_PASSWORD: rootpass
    volumes:
      - db_wp1_data:/var/lib/mysql
    networks:
      - webdev-net
    restart: unless-stopped

volumes:
  wp1_data:
  db_wp1_data:

networks:
  webdev-net:
    external: true

Erläuterungen:

Domain wp1.localhostwird von Traefik per Label erkann
Netzwerk webdev-netalle Container (inkl. Traefik) müssen darin sein
Keine Ports notwendigdank Traefik entfallen individuelle ports:-Einträge
Datenbank-Zugang über phpMyAdminMit Host db_wp1, Benutzer wordpress, Passwort examplepass

Sie starten die einzelnen Web-Instanzen jeweils aus dem Verzeichnis heraus, in dem sich die compose.yaml Datei befindet. Weiter unten zeigen wir, wie man alle Container gleichzeitig per Skript starten kann.

In einem Terminal, z.B. für wp1:

cd WebDev/wp1
# und Starten mit
sudo docker compose up -d

Die Seite im Browser erreichen Sie dann mit der Eingabe von

wp1.localhost

Weiter unten erklären wir, wie Sie eine Landing-Page erstellen, von der aus alle Web-Projekte im Browser aufgerufen werden.

Nun startet wie gewohnt die Installation:

3. phpMyAdmin

Zur Verwaltung der MariaDB- und MySQL-Datenbanken verwenden wir phpMyAdmin. Durch die Umgebungsvariable PMA_ARBITRARY=1 kann man beim Login frei wählen, mit welchem Datenbankhost man sich verbindet – etwa

db_wp1oder db_joomla1

Die WordPress-Datenbank ist vor der Installation noch leer, Joomla haben wir schon eingerichtet, die Datenbank ist mit Inhalten gefüllt.

4. Landing Page

Eine einfache statische Startseite listet alle Projekte mit Links auf. Sie wird über NGINX bereitgestellt und ist unter webdev.localhost erreichbar. Das HTML-Gerüst ist minimal gehalten, das Styling erfolgt per styles.css.

Screenshot der Landingpage, links eine Liste der Projekte, rechts eine Beschreibung.

Netzwerk

Alle Container verwenden dasselbe benannte externe Netzwerk webdev-net, um miteinander zu kommunizieren und von Traefik erkannt zu werden.

Container starten und stoppen per Skript

Für den bequemen Start/Stopp der gesamten Umgebung haben wir zwei Skripte angelegt, die Sie im Terminal aufrufen:

# alle Projekte starten:
sudo bash start-all.sh
# alle Projekte stoppen:
sudo bash stop-all.sh   

Weil docker-compose in unserer Installation Administratorrechte benötigt, also der einzelne Befehl lauten würde:

sudo docker compose up -d

starten wir zunächst ein Terminal als Administrator sudo bash und führen anschließend das Skript mit allen Start- oder Stop-Befehlen aus.

Das Start-Skript im Editor VSCode. Links im Explorer die Projektverzeichnisse.

Ausblick

Die Umgebung lässt sich flexibel erweitern – z. B. um:

  • weitere CMS-Systeme wie Typo3 oder DokuWiki
  • Webmail, Newsletter-Tools oder Shop-Systeme
  • einen internen Mailserver für Testzwecke
  • automatische Zertifikate mit Let’s Encrypt (bei externem Zugriff)

Grafik: Website-Icon