Netzwerkisolation zwischen Compose-Stacks - Dienste gezielt absichern
Netzwerkisolation zwischen Compose-Stacks - Dienste gezielt absichern
Jeder Container, der im selben Docker-Netzwerk ist, kann alle anderen Container in diesem Netzwerk direkt ansprechen — das ist oft mehr Zugriff als nötig.
Das Standard-Verhalten
Ohne explizite Netzwerk-Konfiguration packt Compose alle Services eines Projekts in ein gemeinsames Netzwerk:
# Alle drei Container sind im selben Netzwerk
services:
web:
image: nginx
app:
image: myapp
db:
image: postgres:16
Ergebnis: web kann direkt db:5432 erreichen — obwohl das nie beabsichtigt war. Das Prinzip der geringsten Berechtigung wird verletzt.
Lösung: Mehrere Netzwerke
services:
web:
image: nginx
networks:
- frontend # Web kann nur app erreichen
app:
image: myapp
networks:
- frontend # Erreichbar für web
- backend # Kann db erreichen
db:
image: postgres:16
networks:
- backend # Nur für app erreichbar, NICHT für web
networks:
frontend:
backend:
web und db sind in keinem gemeinsamen Netzwerk — direkte Verbindung ist unmöglich. app sitzt als Brücke zwischen beiden.
Erweitertes Beispiel mit Cache
services:
web:
image: nginx
ports:
- "443:443"
networks:
- frontend
app:
image: myapp
networks:
- frontend
- backend
cache:
image: redis
networks:
- backend # app → cache: ja; web → cache: nein
db:
image: postgres:16
networks:
- backend # app → db: ja; web → db: nein; cache → db: nein
networks:
frontend: # Öffentliche Seite
backend: # Interne Dienste
Internes Netzwerk: kein Internet-Zugriff
networks:
backend:
internal: true # Container in diesem Netz können NICHT ins Internet
Nützlich für Datenbanken, die niemals externe Verbindungen aufbauen sollen. Ein Angreifer, der den DB-Container kompromittiert, kann darüber keine Daten nach außen exfiltrieren.
Netzwerk-Zugriff prüfen
# Welche Netzwerke hat ein Container?
docker inspect --format='{{json .NetworkSettings.Networks}}' myapp | jq 'keys'
# Container im selben Netzwerk?
docker network inspect backend --format='{{range .Containers}}{{.Name}} {{end}}'
# Verbindung testen (aus Container heraus)
docker exec web curl -m 3 http://db:5432 # Sollte fehlschlagen
docker exec app curl -m 3 http://db:5432 # Sollte funktionieren
Netzwerk-Aliases
In manchen Fällen soll ein Container unter mehreren Namen erreichbar sein:
services:
app:
image: myapp
networks:
frontend:
aliases:
- api
- backend-api
backend:
Warum das wichtig ist
- Ohne Isolation:
- Web-Server kompromittiert → direkter Zugriff auf DB
- SQL-Injection im Frontend → direkte DB-Verbindung möglich
- Mit Isolation:
- Web-Server kompromittiert → erreicht nur die App-API
- App muss kompromittiert sein, um DB zu erreichen
- Jede Stufe ist eine zusätzliche Barriere
Das ist kein Ersatz für starke Passwörter und Firewall-Regeln — aber es reduziert die Angriffsfläche deutlich, mit minimalem Konfigurationsaufwand.
Empfehlung für neue Projekte
Mindest-Setup für jede produktive Compose-Anwendung:
networks:
public: # Zwischen Proxy und App
private: # Zwischen App und Datenbank/Cache
Kein Service außer dem Proxy braucht Zugriff auf das public-Netzwerk. Kein Service außer der App braucht Zugriff auf das private-Netzwerk.