Zum Inhalt springen
Serverküche
Suche

Die Suche wird geladen … (nur in der veröffentlichten Seite verfügbar).

Grundlagen Schwierigkeit: Fortgeschritten

Docker-Netzwerke verstehen: bridge, internes DNS & das proxy-Netz

Warum deklariert jedes App-Rezept ein proxy-Netz? Dieser Guide erklärt Docker-Netzwerke, das interne DNS und Container-Isolation an echten Befehlen.

· 7 Min. Lesezeit ·Dauer: ca. 30 Minuten
Inhaltsverzeichnis

networks: [proxy] – dieser Halbsatz taucht in fast jedem App-Rezept der Serverküche auf, meist unkommentiert. Höchste Zeit, ihn einmal zentral zu erklären. Danach verstehst du, wie Container sich finden, warum manche kein Internet brauchen und wie Traefik überhaupt an sie herankommt.

Was bauen wir?

Kein neuer Dienst, sondern das Netzwerk-Modell hinter jedem Docker-Stack. Am Ende weißt du, warum du eigene Netzwerke anlegen solltest statt das Standard-bridge, wie Container sich per Name statt IP erreichen (das interne DNS), was ein internal-Netz ohne Internetzugang bringt und warum das gemeinsame proxy-Netz der Trick ist, mit dem Traefik jede App erreicht. Alle Ausgaben stammen von einem echten Debian 13-Server mit Docker 29.

Schema: Internet über Traefik ins proxy-Netz, die App zusätzlich im internen Netz zur Datenbank ohne Internetzugang
Zwei Netze: proxy verbindet Traefik und App, intern verbindet App und Datenbank – die DB hat keinen Internetzugang

Voraussetzungen

🍳 Empfehlung Anzeige

VPS 1000 G12

4 vCore · 8 GB RAM · 256 GB NVMe

ab 10,36 €/Monat

Ein kleiner VPS reicht, um mehrere Container-Netze durchzuspielen.

Zu netcup →

💶 5 € Gutschein für netcup-Neukunden:36nc17844976032 (nur Neukunden, keine Domains)

Schritt für Schritt

Schritt 1: Was schon da ist

Nach der Installation bringt Docker drei Netzwerke mit:

Terminal
docker network ls
Ausgabe
NETWORK ID     NAME      DRIVER    SCOPE
9d087537e327   bridge    bridge    local
b622109fef73   host      host      local
e12e562ad7f6   none      null      local
  • bridge – das Standard-Netz. Container ohne explizite Netzangabe landen hier. Es funktioniert, hat aber einen entscheidenden Haken (Schritt 3).
  • host – der Container teilt sich den Netzwerk-Stack des Hosts direkt (kein Isolations-Layer, keine Port-Zuordnung). Nur für Sonderfälle.
  • none – gar kein Netzwerk. Für Container, die bewusst offline sein sollen.

Für eigene Stacks nutzt du keines davon direkt, sondern legst eigene Netzwerke an. Warum, zeigt Schritt 3.

Schritt 2: Ein eigenes Netzwerk anlegen

Terminal
docker network create demo-net

Docker erstellt ein bridge-Netz und vergibt automatisch ein Subnetz:

Terminal
docker network inspect demo-net --format 'name={{.Name}} driver={{.Driver}} subnet={{range .IPAM.Config}}{{.Subnet}}{{end}}'
Ausgabe
name=demo-net driver=bridge subnet=172.20.0.0/16

Jeder Container in diesem Netz bekommt eine IP aus 172.20.0.0/16. Aber mit IPs willst du gar nicht arbeiten – sie ändern sich bei jedem Neustart. Der eigentliche Gewinn ist etwas anderes.

Schritt 3: Das interne DNS – Container per Name finden

Starte zwei Container in demo-net: einen Webserver und einen Client.

Terminal
docker run -d --name web --network demo-net nginx:1.29-alpine
docker run -d --name client --network demo-net alpine:3.20 sleep 600

Jetzt der entscheidende Test – der Client erreicht den Webserver über seinen Namen:

Terminal
docker exec client ping -c 2 web
Ausgabe
PING web (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.171 ms
64 bytes from 172.20.0.2: seq=1 ttl=64 time=0.095 ms

Docker löst den Containernamen web automatisch auf die richtige IP auf. Das gilt auch für HTTP:

Terminal
docker exec client wget -qO- http://web/
Ausgabe
<title>Welcome to nginx!</title>

Genau deshalb steht in Compose-Dateien DB_HOST=db statt einer IP: db ist der Servicename, und Docker macht daraus die richtige Adresse. Der Vergleich mit dem Standard-bridge zeigt, warum du es meidest – dort gibt es keine Namensauflösung:

Terminal
docker run -d --name legacy1 nginx:1.29-alpine
docker run --rm alpine:3.20 ping -c 1 legacy1
Ausgabe
ping: bad address 'legacy1'

Compose macht das automatisch

Ein docker compose up legt für den Stack automatisch ein eigenes benanntes Netz an (z. B. meineapp_default) – mit funktionierendem DNS. Deshalb erreichen sich die Services eines Compose-Files immer per Name, ohne dass du etwas tust. Das Standard-bridge betrifft nur Container, die du von Hand mit docker run ohne --network startest.

Schritt 4: Segmentieren – Datenbank ohne Internet

Nicht jeder Container braucht jeden anderen zu sehen. Eine Datenbank soll nur von ihrer App erreichbar sein und braucht selbst kein Internet. Dafür gibt es internal-Netze:

Terminal
docker network create --internal demo-intern

internal: true kappt die Route nach draußen. Der Beweis:

Terminal
docker run --rm --network demo-intern alpine:3.20 \
  sh -c "wget -qT4 -O- http://example.com >/dev/null 2>&1 && echo REACHED || echo BLOCKED"
Ausgabe
BLOCKED

Das ist ein starkes Sicherheitsmuster: Selbst wenn ein Angreifer die Datenbank kompromittiert, kann sie keine Verbindung nach außen aufbauen (kein Nachladen von Schadcode, kein Datenabfluss). Ein typischer Stack nutzt deshalb zwei Netze: ein internal-Netz zwischen App und Datenbank, und das öffentliche proxy-Netz nur zwischen App und Traefik.

Schritt 5: Das proxy-Netz – wie Traefik jede App erreicht

Jetzt der meistkopierte Halbsatz des Katalogs. Traefik läuft in einem eigenen Container und muss mit jeder App reden, um deren Anfragen weiterzuleiten. Container reden aber nur miteinander, wenn sie im selben Netz sind. Die Lösung: ein gemeinsames, dauerhaftes Netz namens proxy.

Terminal
docker network inspect proxy --format 'name={{.Name}} driver={{.Driver}} subnet={{range .IPAM.Config}}{{.Subnet}}{{end}} internal={{.Internal}}'
Ausgabe
name=proxy driver=bridge subnet=172.19.0.0/16 internal=false

Traefik hängt dauerhaft in diesem Netz. Jede neue App tritt ihm bei – in Compose so:

YAML
services:
  meineapp:
    image: beispiel/app:1.0
    networks:
      - proxy        # damit Traefik die App erreicht
      - intern       # private Verbindung zur Datenbank
    labels:
      - "traefik.enable=true"
      # ... die Router-/Service-Labels

networks:
  proxy:
    external: true   # von Traefik angelegt, NICHT neu erstellen
  intern:
    internal: true

Zwei Dinge sind hier zentral: external: true sagt Docker „dieses Netz existiert schon, häng dich nur an“ – legst du es versehentlich neu an, landet die App in einem anderen proxy-Netz als Traefik und ist über die Domain nicht erreichbar (der Klassiker aus dem 502-Troubleshooting). Und über das zweite Netz intern erreicht die App ihre Datenbank, ohne dass diese je im öffentlichen Netz hängt.

Schritt 6: Ports veröffentlichen – nur wo nötig

In allen bisherigen Schritten reden Container untereinander, ohne einen einzigen Port zu veröffentlichen. Ein Port muss nur dann nach außen, wenn der Host oder das Internet direkt zugreifen soll:

Terminal
docker run -d --name pub -p 8099:80 nginx:1.29-alpine
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8099/
Ausgabe
200

-p 8099:80 bindet Host-Port 8099 auf Container-Port 80. In Compose ist das ports: ["8099:80"]. Der wichtige Unterschied zu expose: expose macht einen Port nur für andere Container sichtbar (netzintern), ports öffnet ihn zum Host.

Hinter Traefik keine App-Ports veröffentlichen

Läuft eine App hinter Traefik, braucht (und will) sie kein ports:. Traefik erreicht sie über das proxy-Netz; ein zusätzlich veröffentlichter Port umginge Traefik und damit HTTPS, Middlewares und Firewall-Logik. Veröffentliche nur die Ports von Traefik selbst (80/443). Alles andere bleibt netzintern.

Wenn es nicht funktioniert

Container erreicht anderen nicht per Name (bad address). Beide hängen nicht im selben benannten Netz, oder einer nutzt das Standard-bridge (kein DNS). Prüfe mit docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}' CONTAINER, in welchen Netzen ein Container hängt.

Traefik gibt 502 Bad Gateway. Fast immer sind Traefik und die App in verschiedenen proxy-Netzen, weil das Netz doppelt angelegt wurde. external: true im Compose sicherstellen und mit docker network inspect proxy prüfen, ob beide Container gelistet sind.

network proxy not found beim up. Das externe Netz existiert noch nicht. Einmalig anlegen: docker network create proxy (bzw. Traefik zuerst starten, das es erstellt).

Datenbank hat trotz internal Internet. Sie hängt zusätzlich in einem nicht-internen Netz (z. B. proxy). Ein Container hat die Summe der Zugriffe aller seiner Netze – die DB gehört nur ins interne Netz, nie ins proxy-Netz.

Zwei Stacks kollidieren beim Subnetz. Docker vergibt 172.x-Bereiche automatisch, aber bei vielen Netzen kann der Pool knapp werden (could not find an available, non-overlapping IPv4 address pool). Ungenutzte Netze aufräumen: docker network prune.

Wartung & Backups

  • Netzwerke brauchen kein Backup – sie werden aus der Compose-Datei jederzeit neu erzeugt. Wichtig ist also, dass deine compose.yaml und die networks:-Deklarationen im Backup liegen, nicht der Netz-Zustand selbst.
  • Verwaiste Netze aufräumen. Nach vielen Tests sammeln sich ungenutzte Netze an. docker network ls zeigt sie, docker network prune entfernt alle ohne angehängte Container. Das dauerhafte proxy-Netz bleibt dabei erhalten, solange Traefik läuft.
  • Das proxy-Netz ist Infrastruktur. Behandle es wie Traefik selbst: einmal anlegen, dann in Ruhe lassen. Es aus Versehen zu löschen (network prune bei gestopptem Traefik) zwingt dich, alle Apps neu zu verbinden. Mehr zum sauberen Aufräumen steht in Docker-Stack aktuell halten.

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken

Forgejo: der eigene Git-Server hinter Traefik
Anwendungen Fortgeschritten

Forgejo: der eigene Git-Server hinter Traefik

Forgejo mit Docker & Traefik aufsetzen: eigener Git-Server mit HTTPS, Repos per Web-UI, Klonen über HTTPS und SSH – die …

· 10 Min. Lesezeit