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
💡 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
execist wie Troubleshooting ohne SSH – du schaust von aussen und rätselt. Mitexecgehst 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
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
Weiterführende Links
| 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 |