Zum Inhalt

Block 4 – Netzwerk & Kommunikation

Dauer: ca. 25 Minuten
Ziel: Verstehen wie Container kommunizieren – untereinander und mit der Aussenwelt.

💡 Roter Faden: Wir geben unserem nginx einen zweiten Container als "Backend" und lassen die beiden miteinander sprechen.


4.1 Netzwerk-Grundprinzip

Jeder Container bekommt beim Start eine eigene Netzwerk-Umgebung. Standardmässig ist er isoliert – er sieht nichts von aussen, niemand sieht ihn.

┌─────────────────────────────────────────────────┐
│                     HOST                         │
│                                                  │
│   eth0: 192.168.1.10                            │
│                                                  │
│   ┌─────────────────────────────────────────┐   │
│   │          Bridge-Netzwerk (podman)        │   │
│   │          10.88.0.0/16                   │   │
│   │                                         │   │
│   │  ┌──────────────┐  ┌──────────────┐    │   │
│   │  │  Container 1  │  │  Container 2  │   │   │
│   │  │  10.88.0.2    │  │  10.88.0.3   │   │   │
│   │  └──────────────┘  └──────────────┘   │   │
│   └─────────────────────────────────────────┘   │
└─────────────────────────────────────────────────┘

"Das Bridge-Netzwerk ist wie ein interner Switch – die Container sehen sich, der Host sieht sie, aber von aussen ist nichts erreichbar ohne explizites Port-Forwarding."


4.2 Netzwerk-Modi

Modus Beschreibung Wann verwenden
bridge Standard – eigenes Netzwerk, isoliert Normale Container
host Container nutzt direkt Host-Netzwerk Performance-kritisch, kein Forwarding nötig
none Kein Netzwerk Security, Batch-Jobs
custom Eigenes benanntes Netzwerk Container sollen sich per Name finden
# Modus angeben
podman run --network host nginx
podman run --network none nginx
podman run --network mein-netz nginx

4.3 Port-Forwarding

Damit Container von aussen erreichbar sind, müssen Ports explizit freigegeben werden:

# Host-Port → Container-Port
podman run -p ${PORT}:80 nginx       # Host:${PORT} → Container:80
podman run -p 443:443 nginx       # gleicher Port
podman run -p 127.0.0.1:${PORT}:80 nginx  # nur auf localhost

# Mehrere Ports
podman run -p ${PORT}:80 -p 8443:443 nginx

# Alle exponierten Ports automatisch mappen (zufällige Host-Ports)
podman run -P nginx
# Aktive Port-Mappings anzeigen
podman port mein-nginx
# 80/tcp -> 0.0.0.0:${PORT}

💡 Rootless-Hinweis: Als normaler User sind Ports unter 1024 nicht erlaubt. Port 80 direkt freigeben funktioniert nicht – stattdessen z.B. 8080 oder ${PORT} verwenden.


4.4 Container-zu-Container Kommunikation

Problem mit Standard-Bridge

Im Standard-Bridge-Netzwerk können Container sich nicht per Namen finden – nur per IP:

# Container-IP herausfinden
podman inspect --format '{{.NetworkSettings.IPAddress}}' mein-nginx
# 10.88.0.2

# Andere Container können diese IP ansprechen
podman exec anderer-container curl http://10.88.0.2

IPs können sich ändern – das ist unzuverlässig.

Lösung: Custom Bridge-Netzwerk

In einem benannten Netzwerk kennen sich Container per Namen:

┌──────────────────────────────────────────────┐
│          Custom Netzwerk: mein-netz          │
│                                              │
│  ┌─────────────┐       ┌─────────────┐      │
│  │    nginx    │──────→│   backend   │      │
│  │ mein-nginx  │ :3000 │  mein-backend│     │
│  └─────────────┘       └─────────────┘      │
│   curl http://mein-backend:3000              │
└──────────────────────────────────────────────┘

"Container-DNS im eigenen Netzwerk ist wie /etc/hosts – nur dynamisch und automatisch gepflegt. Solange beide Container im gleichen Netzwerk sind, funktioniert die Namensauflösung."

# Netzwerk erstellen
podman network create mein-netz

# Container im gleichen Netzwerk starten
podman run -d --name mein-nginx   --network mein-netz -p ${PORT}:80 nginx
podman run -d --name mein-backend --network mein-netz httpd

# nginx kann backend per Name ansprechen!
podman exec mein-nginx curl http://mein-backend

4.5 Netzwerk verwalten

# Alle Netzwerke anzeigen
podman network ls

# Netzwerk inspizieren
podman network inspect mein-netz

# Container zu bestehendem Netzwerk hinzufügen
podman network connect mein-netz mein-nginx

# Container aus Netzwerk entfernen
podman network disconnect mein-netz mein-nginx

# Netzwerk löschen (nur wenn keine Container verbunden)
podman network rm mein-netz

# Unbenutzte Netzwerke aufräumen
podman network prune

4.6 Netzwerk debuggen

# Von innen prüfen ob Container erreichbar
podman exec mein-nginx curl http://mein-backend

# DNS-Auflösung testen
podman exec mein-nginx nslookup mein-backend
# Falls nslookup fehlt: dnf install -y bind-utils
# Alternative ohne nslookup:
podman exec mein-nginx cat /etc/resolv.conf
podman exec mein-nginx curl http://mein-backend

# Netzwerk-Interfaces im Container
podman exec mein-nginx ip addr

# Verbindungen aus dem Container
podman exec mein-nginx ss -tlnp
# Falls ss fehlt: dnf install -y iproute
# Alternative ohne ss:
podman exec mein-nginx cat /proc/net/tcp

# Welches Netzwerk hat der Container?
podman inspect --format '{{.NetworkSettings.Networks}}' mein-nginx

"Netzwerk-Debugging ohne exec ist wie Troubleshooting ohne SSH – du schaust von aussen und rätselt. Mit exec gehst du rein und testest direkt."


4.7 iptables – was Container im Hintergrund schreiben

Container-Technologien schreiben automatisch iptables- oder nftables-Regeln – ohne zu fragen. Das ist wichtig zu wissen wenn auf einem Server unerklärliche Netzwerk-Probleme auftreten.

Wer schreibt was?

Technologie iptables-Verhalten
Podman rootful Erstellt NAT-Regeln für Port-Forwarding
Podman rootless Kein iptables – verwendet pasta oder slirp4netns im User-Namespace
Docker Erstellt eigene DOCKER-Chain, schreibt FORWARD-Regeln – sehr aggressiv
Kubernetes / k3s Viele Regeln für Service-Routing via kube-proxy

"Wenn ihr auf einem Server plötzlich komische Netzwerk-Probleme habt – Ports die nicht erreichbar sind obwohl der Dienst läuft, oder Traffic der unerwartet umgeleitet wird – lohnt sich immer ein Blick in iptables. Container-Technologien schreiben da rein ohne zu fragen."

iptables/nftables inspizieren

# Alle Regeln anzeigen
sudo iptables -L -n -v

# NAT-Regeln – hier sieht man Port-Forwardings der Container
sudo iptables -t nat -L -n -v

# Nur Container-relevante Chains
sudo iptables -t nat -L -n -v | grep -E 'DOCKER|PODMAN|KUBE'

# nftables (auf neueren RHEL 9 Systemen)
sudo nft list ruleset

Typische Situation: Docker kollidiert mit bestehender Firewall

Docker schreibt seine DOCKER-Chain direkt in FILTER und NAT und umgeht dabei oft bestehende firewalld-Regeln. Das kann dazu führen dass Ports offen sind die eigentlich gesperrt sein sollten.

# Docker-spezifische NAT-Regeln
sudo iptables -t nat -L DOCKER -n -v

# Podman rootful – sauberer, respektiert firewalld
sudo iptables -t nat -L -n -v | grep PODMAN

"Podman rootless macht gar nichts mit iptables – das ist einer der grossen Sicherheitsvorteile. Rootless Container hinterlassen keine Spuren in den Netzwerk-Regeln des Hosts."


Orientierungstabelle – Netzwerk

Frage Befehl
Welche Ports sind gemappt? podman port <n>
Welche IP hat der Container? podman inspect --format '{{.NetworkSettings.IPAddress}}' <n>
In welchem Netzwerk ist der Container? podman inspect --format '{{.NetworkSettings.Networks}}' <n>
Kann Container A Container B erreichen? podman exec <a> curl http://<b>
Alle Netzwerke anzeigen podman network ls
Container-Regeln in iptables sehen sudo iptables -t nat -L -n -v
Nur Docker/Podman/Kube-Chains sudo iptables -t nat -L -n -v \| grep -E 'DOCKER\|PODMAN\|KUBE'

Übung 4 – Zwei Container verbinden

🔴 Roter Faden: Wir fügen unserem nginx ein "Backend" hinzu und lassen beide miteinander kommunizieren.

Aufgabe 4a – Port-Forwarding verstehen

# nginx auf deinem Port starten (falls nicht läuft)
podman run -d \
  --name mein-nginx \
  -p ${PORT}:80 \
  -v ~/webroot:/usr/share/nginx/html:ro \
  docker.io/library/nginx:latest

# Port-Mapping anzeigen
podman port mein-nginx

# Erreichbar?
curl http://localhost:${PORT}

Aufgabe 4b – Custom Netzwerk und zwei Container

# 1. Netzwerk erstellen
podman network create kurs-netz

# 2. nginx im neuen Netzwerk starten
podman stop mein-nginx && podman rm mein-nginx
podman run -d \
  --name mein-nginx \
  --network kurs-netz \
  -p ${PORT}:80 \
  -v ~/webroot:/usr/share/nginx/html:ro \
  docker.io/library/nginx:latest

# 3. Zweiten Webserver als "Backend" starten
podman run -d \
  --name mein-backend \
  --network kurs-netz \
  docker.io/library/httpd:latest

# 4. Können sie sich per Namen finden?
podman exec mein-nginx curl http://mein-backend

Fragen: 1. Was antwortet mein-backend auf die Anfrage von mein-nginx? 2. Was passiert wenn du mein-backend ohne --network kurs-netz startest?

Aufgabe 4c – Netzwerk inspizieren

podman network inspect kurs-netz

Fragen: 1. Welche IPs haben die Container? 2. Welcher Subnet wird verwendet?


Musterlösung Übung 4

4a

podman port mein-nginx
# 80/tcp -> 0.0.0.0:${PORT}

curl http://localhost:${PORT}
# → Eigene index.html aus Block 3

4b

podman exec mein-nginx curl http://mein-backend
# <html><body><h1>It works!</h1></body></html>
# → Apache Default-Page von httpd-Container

Ohne --network kurs-netz:

podman run -d --name mein-backend docker.io/library/httpd:latest
podman exec mein-nginx curl http://mein-backend
# curl: Could not resolve host: mein-backend
# → Kein DNS ohne gemeinsames Netzwerk!

4c

podman network inspect kurs-netz
# "Subnets": [{"Subnet": "10.89.0.0/24"}]
# Container haben IPs wie 10.89.0.2 und 10.89.0.3

Thema Link
Podman Networking docs.podman.io – podman-network
Red Hat – Container Networking access.redhat.com – Container Networking
Netavark – Podman Netzwerk-Backend github.com/containers/netavark