Netzwerkprobleme zwischen Containern debuggen

Netzwerkprobleme zwischen Containern debuggen

Container im selben Stack können sich gegenseitig nicht erreichen — diese Checkliste führt systematisch zur Ursache.

Das häufigste Missverständnis: localhost

Innerhalb eines Containers ist localhost der Container selbst — nicht der Host und nicht ein anderer Container. Wer curl http://localhost:3000 in Container A ausführt, erreicht Port 3000 von Container A, nicht von Container B.

Richtig: Andere Container über ihren Service-Namen ansprechen.

Checkliste Schritt für Schritt

1. Gleiches Netzwerk prüfen

docker inspect containerA --format '{{json .NetworkSettings.Networks}}'
docker inspect containerB --format '{{json .NetworkSettings.Networks}}'

Beide müssen im selben Netzwerk sein. Bei Compose passiert das automatisch — außer ein Container hat network_mode: host oder ein explizit anderes Netzwerk zugewiesen.

2. Service-Namen vs. Container-Namen

In Compose-Stacks ist der Service-Name der DNS-Name, nicht der Container-Name:

services:
  api:          # ← dieser Name ist der DNS-Name
    image: myapi
  web:
    image: nginx
    # Richtig: proxy_pass http://api:3000;
    # Falsch:  proxy_pass http://myproject-api-1:3000;

3. Konnektivität testen

# Ping-Test (erfordert iputils-ping im Container)
docker exec containerA ping containerB

# HTTP-Test — direkter und praktikabler
docker exec containerA curl http://containerB:3000

# DNS-Auflösung prüfen
docker exec containerA nslookup containerB

4. Lauscht der Zieldienst überhaupt?

docker exec containerB ss -tlnp
# oder
docker exec containerB netstat -tlnp

Wenn der Dienst nur auf 127.0.0.1:3000 lauscht statt auf 0.0.0.0:3000, ist er nur innerhalb des Containers selbst erreichbar — nicht von anderen Containern.

5. Firewall-Regeln auf dem Host

iptables-Regeln auf dem Host können Docker-internen Traffic blockieren:

sudo iptables -L DOCKER-USER -n

Docker verwaltet seine eigenen Regeln — manuelle Eingriffe können unbeabsichtigt den Inter-Container-Traffic sperren.

DNS funktioniert nur auf user-defined Networks

Das ist ein wichtiger Docker-Gotcha:

  • Default bridge (docker0): Kein DNS. Container können sich nur per IP-Adresse erreichen — und IPs ändern sich bei jedem Start.
  • User-defined bridge (manuell erstellt oder via Compose): Eingebauter DNS-Server. Container erreichbar per Service-/Container-Name.

Compose erstellt automatisch ein user-defined Network. Wer Container manuell mit docker run startet, muss ein Netzwerk explizit erstellen:

docker network create mynet
docker run --network mynet --name api myapi
docker run --network mynet --name web nginx

Jetzt kann web den Host api per Name auflösen.

Netzwerkübersicht

# Alle Netzwerke anzeigen
docker network ls

# Container in einem Netzwerk anzeigen
docker network inspect mynet --format '{{range .Containers}}{{.Name}} {{end}}'

Häufige Ursachen auf einen Blick

| Problem | Diagnose | Lösung |
|---------|----------|--------|
| Container in unterschiedlichen Netzwerken | docker inspect → Networks vergleichen | Beide in dasselbe Netzwerk |
| localhost statt Service-Name | Logs / Konfiguration | Service-Name verwenden |
| Dienst lauscht nur auf 127.0.0.1 | ss -tlnp im Container | App-Konfiguration auf 0.0.0.0 |
| Default bridge (kein DNS) | docker network ls | User-defined Network verwenden |

Weiterführend

Die hier eingesetzten Tools — ss, ip, ping, dig — sind klassische Linux-Netzwerkwerkzeuge. Mehr dazu auf nolr.nexon.cyou.