Die Grundstruktur einer docker-compose.yml - was wirklich reingehört
Die Grundstruktur einer docker-compose.yml - was wirklich reingehört
Eine docker-compose.yml zu schreiben ist schnell getan — aber viele Beispiele im Netz enthalten veraltete Felder, fehlende Konfiguration und häufige Fallen. Hier ist was tatsächlich in eine moderne Compose-Datei gehört.
Minimales, funktionsfähiges Beispiel
services:
web:
image: nginx:1.25.3
container_name: mein-web
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
Das reicht für die meisten einfachen Anwendungen.
Das version-Feld ist obsolet
In älteren Beispielen steht ganz oben:
version: "3.9" # veraltet — nicht mehr notwendig
Das version-Feld ist seit Docker Compose v2 deprecated und wird ignoriert. Einfach weglassen.
image vs. build
services:
app:
# Fertiges Image aus Registry
image: myregistry/myapp:2.1.0
app-dev:
# Eigenes Dockerfile bauen
build:
context: .
dockerfile: Dockerfile.dev
restart-Policy
restart: no # nie neu starten (Standard)
restart: always # immer — auch nach manuell docker stop
restart: unless-stopped # immer, außer wenn manuell gestoppt
restart: on-failure # nur bei Exit Code != 0
unless-stopped ist für die meisten Produktions-Dienste die richtige Wahl.
Ports: die YAML-Falle
# Gefährlich: YAML interpretiert 8080:80 als Oktalzahl!
ports:
- 8080:80 # Fehler bei bestimmten Ports (z.B. 0600:80)
# Immer Strings verwenden
ports:
- "8080:80"
- "127.0.0.1:8080:80" # nur auf localhost erreichbar
volumes: named vs. bind
services:
db:
image: postgres:16
volumes:
# Named Volume (von Docker verwaltet)
- db-data:/var/lib/postgresql/data
# Bind Mount (Host-Pfad direkt)
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
volumes:
db-data: # Named Volume muss hier deklariert werden
environment vs. env_file
services:
app:
# Direkt in der Compose-Datei (für nicht-sensitive Werte)
environment:
- APP_ENV=production
- PORT=8080
# Aus Datei laden (für Secrets, .env nicht ins Git!)
env_file:
- .env
Netzwerke
Ohne Konfiguration erstellt Compose ein Standard-Bridge-Netzwerk. Alle Services in der Compose-Datei können sich über ihren Service-Namen erreichen.
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
backend:
Vollständiges Beispiel
services:
web:
image: nginx:1.25.3
container_name: mein-web
restart: unless-stopped
ports:
- "127.0.0.1:80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
networks:
- frontend
app:
build: .
container_name: mein-app
restart: unless-stopped
env_file: .env
environment:
- NODE_ENV=production
volumes:
- app-logs:/app/logs
networks:
- frontend
- backend
db:
image: postgres:16-alpine
container_name: mein-db
restart: unless-stopped
env_file: .env.db
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
volumes:
db-data:
app-logs:
networks:
frontend:
backend: