Zum Hauptinhalt springen Zur Navigation springen Zur Fußzeile springen

Netzwerk

Dienste über den Reverse Proxy, Docker-Labels, TLS-Zertifikate, DNS und TCP/UDP-Portweiterleitung für externe Erreichbarkeit bereitstellen.

Netzwerk

Diese Seite erklärt, wie Dienste, die in isolierten Docker-Daemons laufen, aus dem Internet erreichbar werden. Sie behandelt das Reverse-Proxy-System, Docker-Labels für das Routing, TLS-Zertifikate, DNS und TCP/UDP-Portweiterleitung.

Wie Dienste ihre Loopback-IPs erhalten und das .rediacc.json-Slot-System funktioniert, erfahren Sie unter Dienste.

Funktionsweise

Rediacc verwendet ein Zwei-Komponenten-Proxy-System, um externen Traffic an Container weiterzuleiten:

  1. Route Server — ein systemd-Dienst, der laufende Container über alle Repository-Docker-Daemons hinweg erkennt. Er inspiziert Container-Labels und generiert Routing-Konfiguration, die als YAML-Endpunkt bereitgestellt wird.
  2. Traefik — ein Reverse Proxy, der den Route Server alle 5 Sekunden abfragt und die erkannten Routen anwendet. Er übernimmt HTTP/HTTPS-Routing, TLS-Terminierung und TCP/UDP-Weiterleitung.

Der Ablauf sieht so aus:

Internet → Traefik (Ports 80/443/TCP/UDP)
               ↓ fragt alle 5s ab
           Route Server (erkennt Container)
               ↓ inspiziert Labels
           Docker Daemons (/var/run/rediacc/docker-*.sock)

           Container (gebunden an 127.x.x.x Loopback-IPs)

Wenn Sie die richtigen Labels zu einem Container hinzufügen und ihn mit renet compose starten, wird er automatisch routbar — keine manuelle Proxy-Konfiguration nötig.

The route server binary is kept in sync with your CLI version. When the CLI updates the renet binary on a machine, the route server is automatically restarted (~1–2 seconds). This causes no downtime, Traefik continues serving traffic with its last known configuration during the restart and picks up the new config on the next poll. Existing client connections are not affected. Your application containers are not touched.

Docker-Labels

Das Routing wird über Docker-Container-Labels gesteuert. Es gibt zwei Stufen:

Stufe 1: rediacc.*-Labels (Automatisch)

Diese Labels werden automatisch von renet compose beim Starten von Diensten injiziert. Sie müssen sie nicht manuell hinzufügen.

LabelBeschreibungBeispiel
rediacc.service_nameDienst-Identitätmyapp
rediacc.service_ipZugewiesene Loopback-IP127.0.11.2
rediacc.network_idDocker-Daemon-ID des Repositories2816
rediacc.repo_nameRepository namemarketing
rediacc.tcp_portsTCP ports the service listens on8080,8443
rediacc.udp_portsUDP ports the service listens on53

Wenn ein Container nur rediacc.*-Labels hat (kein traefik.enable=true), generiert der Route Server eine Auto-Route unter Verwendung des Repository-Namens und der Maschinen-Subdomain:

{service}.{repoName}.{machineName}.{baseDomain}

Zum Beispiel erhält ein Dienst namens myapp in einem Repository namens marketing auf Maschine server-1 mit Basis-Domain example.com:

myapp.marketing.server-1.example.com

Jedes Repository hat seine eigene Subdomain-Ebene, sodass Forks und verschiedene Repos nie kollidieren. Wenn Sie ein Repository forken (z.B. marketing-staging), erhält der Fork automatisch eigene Routen. Für Dienste mit eigenen Domains verwenden Sie Stufe-2-Labels oder das rediacc.domain-Label.

Benutzerdefinierte Domain via rediacc.domain

Sie können eine benutzerdefinierte Domain für einen Dienst über das rediacc.domain-Label in Ihrer docker-compose.yml festlegen. Sowohl Kurznamen als auch vollständige Domains werden unterstützt:

labels:
  # Kurzname, wird zu cloud.example.com aufgelöst unter Verwendung der baseDomain der Maschine
  - "rediacc.domain=cloud"

  # Vollständige Domain, wird wie angegeben verwendet
  - "rediacc.domain=cloud.example.com"

Ein Wert ohne Punkte wird als Kurzname behandelt und die baseDomain der Maschine wird automatisch angehängt. Ein Wert mit Punkten wird als vollständige Domain verwendet.

Wenn machineName konfiguriert ist, erhalten Dienste mit benutzerdefinierter Domain zwei Routen: eine auf der Basis-Domain (cloud.example.com) und eine auf der Maschinen-Subdomain (cloud.server-1.example.com).

Stufe 2: traefik.*-Labels (Benutzerdefiniert)

Fügen Sie diese Labels in Ihre docker-compose.yml ein, wenn Sie benutzerdefiniertes Domain-Routing, TLS oder bestimmte Einstiegspunkte wünschen. Das Setzen von traefik.enable=true weist den Route Server an, Ihre benutzerdefinierten Regeln anstelle einer Auto-Route zu verwenden.

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
  - "traefik.http.routers.myapp.entrypoints=websecure,websecure-v6"
  - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
  - "traefik.http.services.myapp.loadbalancer.server.port=8080"

Diese verwenden die Standard-Traefik v3 Label-Syntax.

Tipp: Rein interne Dienste (Datenbanken, Caches, Nachrichtenwarteschlangen) sollten kein traefik.enable=true haben. Sie benötigen nur rediacc.*-Labels, die automatisch injiziert werden.

HTTP/HTTPS-Dienste bereitstellen

Voraussetzungen

  1. Infrastruktur auf der Maschine konfiguriert (Maschineneinrichtung — Infrastruktur-Konfiguration):

    # Gemeinsame Zugangsdaten (einmal pro Konfiguration, gilt für alle Maschinen)
    rdc config infra set -m server-1 \
      --cert-email admin@example.com \
      --cf-dns-token your-cloudflare-api-token
    
    # Maschinenspezifische Einstellungen
    rdc config infra set -m server-1 \
      --public-ipv4 203.0.113.50 \
      --base-domain example.com
    
    rdc config infra push -m server-1
  2. DNS-Einträge, die Ihre Domain auf die öffentliche IP des Servers verweisen (siehe DNS-Konfiguration unten).

Labels hinzufügen

Fügen Sie traefik.*-Labels zu den Diensten hinzu, die Sie in Ihrer docker-compose.yml bereitstellen möchten:

services:
  myapp:
    image: myapp:latest
    environment:
      - LISTEN_ADDR=${MYAPP_IP}:8080
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
      - "traefik.http.routers.myapp.entrypoints=websecure,websecure-v6"
      - "traefik.http.routers.myapp.tls.certresolver=letsencrypt"
      - "traefik.http.services.myapp.loadbalancer.server.port=8080"

  database:
    image: postgres:17
    command: ["-c", "listen_addresses=${DATABASE_IP}"]
    # Keine Traefik-Labels, Datenbank ist nur intern
LabelZweck
traefik.enable=trueAktiviert benutzerdefiniertes Traefik-Routing für diesen Container
traefik.http.routers.{name}.ruleRouting-Regel — typischerweise Host(\domain`)`
traefik.http.routers.{name}.entrypointsAuf welchen Ports gelauscht wird: websecure (HTTPS IPv4), websecure-v6 (HTTPS IPv6)
traefik.http.routers.{name}.tls.certresolverZertifikat-Resolver — verwenden Sie letsencrypt für automatisches Let’s Encrypt
traefik.http.services.{name}.loadbalancer.server.portDer Port, auf dem Ihre Anwendung im Container lauscht

Der {name} in den Labels ist ein beliebiger Bezeichner — er muss nur über zusammengehörige Router-/Service-/Middleware-Labels konsistent sein.

Hinweis: Die rediacc.*-Labels (rediacc.service_name, rediacc.service_ip, rediacc.network_id) werden automatisch von renet compose injiziert. Sie müssen sie nicht in Ihre Compose-Datei einfügen.

TLS-Zertifikate

TLS-Zertifikate werden automatisch über Let’s Encrypt mittels der Cloudflare DNS-01-Challenge bezogen. Die Zugangsdaten werden einmal pro Konfiguration eingerichtet (gemeinsam für alle Maschinen):

rdc config infra set -m server-1 \
  --cert-email admin@example.com \
  --cf-dns-token your-cloudflare-api-token

Auto-Routen verwenden Wildcard-Zertifikate auf Repository-Subdomain-Ebene (*.marketing.server-1.example.com) anstelle von Zertifikaten pro Dienst. Dies vermeidet Let’s Encrypt-Ratenlimits und beschleunigt den Start. Routen mit benutzerdefinierten Domains verwenden Maschinen-Wildcards (*.server-1.example.com).

Für Stufe-2-Routen mit traefik.http.routers.{name}.tls.certresolver=letsencrypt werden Wildcard-Domain-SANs automatisch basierend auf dem Hostnamen der Route injiziert.

Das Cloudflare DNS API-Token benötigt Zone:DNS:Edit-Berechtigung für die Domains, die Sie absichern möchten.

TCP/UDP-Portweiterleitung

Für Nicht-HTTP-Protokolle (Mailserver, DNS, extern bereitgestellte Datenbanken) verwenden Sie TCP/UDP-Portweiterleitung.

Schritt 1: Ports registrieren

Fügen Sie die erforderlichen Ports bei der Infrastruktur-Konfiguration hinzu:

rdc config infra set -m server-1 \
  --tcp-ports 25,143,465,587,993 \
  --udp-ports 53

rdc config infra push -m server-1

Dies erstellt Traefik-Einstiegspunkte namens tcp-{port} und udp-{port}.

Plain TCP Example (Database)

To expose a database externally without TLS passthrough (Traefik forwards raw TCP):

services:
  postgres:
    image: postgres:17
    command: -c listen_addresses=${POSTGRES_IP} -c port=5432
    labels:
      - "traefik.enable=true"
      - "traefik.tcp.routers.mydb.entrypoints=tcp-5432"
      - "traefik.tcp.routers.mydb.rule=HostSNI(`*`)"
      - "traefik.tcp.services.mydb.loadbalancer.server.port=5432"

Port 5432 is pre-configured (see below), so no --tcp-ports setup is needed.

Security note: Exposing a database to the internet is a risk. Use this only when remote clients need direct access. For most setups, keep the database internal and connect through your application.

Nach dem Hinzufügen oder Entfernen von Ports führen Sie immer rdc config infra push erneut aus, um die Proxy-Konfiguration zu aktualisieren.

Schritt 2: TCP/UDP-Labels hinzufügen

Verwenden Sie traefik.tcp.*- oder traefik.udp.*-Labels in Ihrer Compose-Datei:

services:
  mail-server:
    image: ghcr.io/docker-mailserver/docker-mailserver:latest
    labels:
      - "traefik.enable=true"

      # SMTP (Port 25)
      - "traefik.tcp.routers.mail-smtp.entrypoints=tcp-25"
      - "traefik.tcp.routers.mail-smtp.rule=HostSNI(`*`)"
      - "traefik.tcp.routers.mail-smtp.service=mail-smtp"
      - "traefik.tcp.services.mail-smtp.loadbalancer.server.port=25"

      # IMAPS (Port 993), TLS-Passthrough
      - "traefik.tcp.routers.mail-imaps.entrypoints=tcp-993"
      - "traefik.tcp.routers.mail-imaps.rule=HostSNI(`mail.example.com`)"
      - "traefik.tcp.routers.mail-imaps.tls.passthrough=true"
      - "traefik.tcp.routers.mail-imaps.service=mail-imaps"
      - "traefik.tcp.services.mail-imaps.loadbalancer.server.port=993"

Wichtige Konzepte:

  • HostSNI(\*`)` stimmt mit jedem Hostnamen überein (für Protokolle, die kein SNI senden, wie unverschlüsseltes SMTP)
  • tls.passthrough=true bedeutet, dass Traefik die rohe TLS-Verbindung weiterleitet, ohne zu entschlüsseln — die Anwendung übernimmt die TLS-Verarbeitung selbst
  • Einstiegspunkt-Namen folgen der Konvention tcp-{port} oder udp-{port}

Vorkonfigurierte Ports

Die folgenden TCP/UDP-Ports haben standardmäßig Einstiegspunkte (kein Hinzufügen über --tcp-ports erforderlich). Einstiegspunkte werden nur für konfigurierte Adressfamilien generiert, IPv4-Einstiegspunkte erfordern --public-ipv4, IPv6-Einstiegspunkte erfordern --public-ipv6:

PortProtokollHäufige Verwendung
80HTTPWeb (automatische Weiterleitung zu HTTPS)
443HTTPSWeb (TLS)
3306TCPMySQL/MariaDB
5432TCPPostgreSQL
6379TCPRedis
27017TCPMongoDB
11211TCPMemcached
5672TCPRabbitMQ
9092TCPKafka
53UDPDNS
10000–10010TCPDynamischer Bereich (automatische Zuordnung)

DNS-Konfiguration

Automatisches DNS (Cloudflare)

Wenn --cf-dns-token konfiguriert ist, erstellt rdc config infra push automatisch die erforderlichen DNS-Einträge in Cloudflare:

EintragTypInhaltErstellt von
server-1.example.comA / AAAAÖffentliche IP der Maschinepush-infra
*.server-1.example.comA / AAAAÖffentliche IP der Maschinepush-infra
*.marketing.server-1.example.comA / AAAAÖffentliche IP der Maschinerepo up

Maschinen-Einträge werden von push-infra erstellt und decken Routen mit benutzerdefinierten Domains (rediacc.domain) ab. Pro-Repository-Wildcard-Einträge werden automatisch von repo up erstellt und decken Auto-Routen für dieses Repository ab.

Dies ist idempotent, bestehende Einträge werden aktualisiert, wenn sich die IP ändert, und bleiben unverändert, wenn sie bereits korrekt sind.

Der Basis-Domain-Wildcard (*.example.com) muss manuell erstellt werden, wenn Sie benutzerdefinierte Domain-Labels wie rediacc.domain=erp verwenden.

Manuelles DNS

Wenn Sie Cloudflare nicht verwenden oder DNS manuell verwalten, erstellen Sie A- (IPv4) und/oder AAAA- (IPv6) Einträge:

# Maschinen-Subdomain (für Routen mit benutzerdefinierter Domain wie rediacc.domain=erp)
server-1.example.com           A     203.0.113.50
*.server-1.example.com         A     203.0.113.50
*.server-1.example.com         AAAA  2001:db8::1

# Pro-Repository-Wildcards (für Auto-Routen wie myapp.marketing.server-1.example.com)
*.marketing.server-1.example.com    A     203.0.113.50
*.marketing.server-1.example.com    AAAA  2001:db8::1

# Basis-Domain-Wildcard (für Dienste mit benutzerdefinierter Domain wie rediacc.domain=erp)
*.example.com                  A     203.0.113.50

Mit konfiguriertem Cloudflare DNS werden Pro-Repository-Wildcard-Einträge automatisch von repo up erstellt. Bei mehreren Maschinen erhält jede Maschine ihre eigenen DNS-Einträge, die auf ihre eigene IP verweisen.

Middlewares

Traefik-Middlewares modifizieren Anfragen und Antworten. Wenden Sie sie über Labels an.

HSTS (HTTP Strict Transport Security)

labels:
  - "traefik.http.middlewares.myapp-hsts.headers.stsSeconds=15768000"
  - "traefik.http.middlewares.myapp-hsts.headers.stsIncludeSubdomains=true"
  - "traefik.http.middlewares.myapp-hsts.headers.stsPreload=true"
  - "traefik.http.routers.myapp.middlewares=myapp-hsts"

Pufferung für große Datei-Uploads

labels:
  - "traefik.http.middlewares.myapp-buffering.buffering.maxRequestBodyBytes=536870912"
  - "traefik.http.routers.myapp.middlewares=myapp-buffering"

Mehrere Middlewares

Verketten Sie Middlewares durch Kommatrennung:

labels:
  - "traefik.http.routers.myapp.middlewares=myapp-hsts,myapp-buffering"

Die vollständige Liste verfügbarer Middlewares finden Sie in der Traefik-Middleware-Dokumentation.

Diagnose

Wenn ein Dienst nicht erreichbar ist, verbinden Sie sich per SSH mit dem Server und prüfen Sie die Route-Server-Endpunkte:

Gesundheitsprüfung

curl -s http://127.0.0.1:7111/health | python3 -m json.tool

Zeigt den Gesamtstatus, die Anzahl erkannter Router und Dienste und ob Auto-Routen aktiviert sind.

Erkannte Routen

curl -s http://127.0.0.1:7111/routes.json | python3 -m json.tool

Listet alle HTTP-, TCP- und UDP-Router mit ihren Regeln, Einstiegspunkten und Backend-Diensten auf.

Port-Zuordnungen

curl -s http://127.0.0.1:7111/ports | python3 -m json.tool

Zeigt TCP- und UDP-Port-Zuordnungen für dynamisch zugewiesene Ports.

Häufige Probleme

ProblemUrsacheLösung
Dienst nicht in RoutenContainer läuft nicht oder Labels fehlenMit docker ps auf dem Repository-Daemon überprüfen; Labels prüfen
Zertifikat nicht ausgestelltDNS zeigt nicht auf den Server oder ungültiges Cloudflare-TokenDNS-Auflösung überprüfen; Cloudflare-API-Token-Berechtigungen prüfen
502 Bad GatewayAnwendung lauscht nicht auf dem deklarierten PortÜberprüfen, ob die App an ihre {SERVICE}_IP gebunden ist und der Port mit loadbalancer.server.port übereinstimmt
TCP-Port nicht erreichbarPort nicht in der Infrastruktur registriertrdc config infra set --tcp-ports ... und push-infra ausführen
Route server running old versionBinary was updated but service not restartedHappens automatically on provisioning; manual: sudo systemctl restart rediacc-router
STUN/TURN relay not reachableRelay addresses cached at startupRecreate the service after DNS or IP changes so it picks up the new network config

Vollständiges Beispiel

Dieses Beispiel stellt eine Webanwendung mit einer PostgreSQL-Datenbank bereit. Die App ist öffentlich unter app.example.com mit TLS erreichbar; die Datenbank ist nur intern verfügbar.

docker-compose.yml

services:
  webapp:
    image: myregistry/webapp:latest
    environment:
      DATABASE_URL: postgresql://app:changeme@${POSTGRES_IP}:5432/webapp
      LISTEN_ADDR: ${WEBAPP_IP}:3000
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.webapp.rule=Host(`app.example.com`)"
      - "traefik.http.routers.webapp.entrypoints=websecure,websecure-v6"
      - "traefik.http.routers.webapp.tls.certresolver=letsencrypt"
      - "traefik.http.services.webapp.loadbalancer.server.port=3000"
      # HSTS
      - "traefik.http.middlewares.webapp-hsts.headers.stsSeconds=15768000"
      - "traefik.http.middlewares.webapp-hsts.headers.stsIncludeSubdomains=true"
      - "traefik.http.routers.webapp.middlewares=webapp-hsts"

  postgres:
    image: postgres:17
    environment:
      POSTGRES_DB: webapp
      POSTGRES_USER: app
      POSTGRES_PASSWORD: changeme
    command: -c listen_addresses=${POSTGRES_IP} -c port=5432
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    # Keine Traefik-Labels, nur intern

Rediaccfile

#!/bin/bash

up() {
    mkdir -p data/postgres
    renet compose -- up -d
}

down() {
    renet compose -- down
}

DNS

Erstellen Sie einen A-Eintrag, der app.example.com auf die öffentliche IP Ihres Servers verweist:

app.example.com   A   203.0.113.50

Bereitstellung

rdc repo up --name my-app -m server-1 --mount

Innerhalb weniger Sekunden erkennt der Route Server den Container, Traefik übernimmt die Route, fordert ein TLS-Zertifikat an, und https://app.example.com ist live.