Was ist Docker Compose?
Docker Compose ist ein Tool zur Definition und Verwaltung von Multi-Container Docker-Applikationen. Statt jeden Container einzeln mit docker run zu starten, definieren Sie alle Services in einer docker-compose.yml Datei.
Vorteile von Docker Compose:
- ✅ Deklarative Konfiguration: Komplette Infrastruktur in einer YAML-Datei
- ✅ Ein-Befehl-Deployment:
docker-compose upstartet alle Container - ✅ Service-Isolation: Jeder Service läuft in eigenem Container, aber kann kommunizieren
- ✅ Netzwerk-Management: Automatisches privates Netzwerk zwischen Containern
- ✅ Volume-Persistenz: Daten bleiben erhalten nach Container-Neustart
- ✅ Entwicklungs- & Produktions-Umgebungen: Gleiche Compose-Datei, verschiedene Configs
🎯 Wann Docker Compose verwenden?
Ideal für: Entwicklungsumgebungen, Test-Stacks, kleinere Produktions-Deployments (1-5 Server).
Nicht ideal für: Hochverfügbare Cluster (>10 Server) → Kubernetes ist besser.
Docker Compose Installation
Linux (Ubuntu/Debian):
# Docker Compose V2 (Plugin) - empfohlen
sudo apt-get update
sudo apt-get install docker-compose-plugin
# Verify Installation
docker compose version
macOS & Windows:
Docker Compose ist in Docker Desktop enthalten (automatisch installiert).
docker-compose.yml Grundstruktur
Eine docker-compose.yml Datei definiert Services (Container), Networks und Volumes.
version: '3.8' # Compose-Datei-Version
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
database:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: geheim123
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Wichtige Schlüsselwörter:
- services: Liste aller Container (z.B. web, database, cache)
- image: Docker-Image (z.B.
nginx:latest,mysql:8.0) - ports: Port-Mapping (Host:Container, z.B.
80:80) - environment: Umgebungsvariablen für Container
- volumes: Persistenter Speicher (überlebt Container-Neustarts)
- depends_on: Start-Reihenfolge (Service A wartet auf Service B)
- networks: Eigene Netzwerke definieren
Beispiel 1: WordPress mit MySQL
Der Klassiker: WordPress benötigt einen Webserver (PHP) + Datenbank (MySQL).
docker-compose.yml:
version: '3.8'
services:
# MySQL-Datenbank
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: rootPasswort123
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wpPasswort456
volumes:
- db_data:/var/lib/mysql
networks:
- wordpress_network
# WordPress
wordpress:
image: wordpress:latest
restart: always
depends_on:
- db
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wpPasswort456
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
networks:
- wordpress_network
volumes:
db_data:
wordpress_data:
networks:
wordpress_network:
Starten:
# Im gleichen Verzeichnis wie docker-compose.yml
docker compose up -d
# Logs anzeigen
docker compose logs -f
# Öffne Browser: http://localhost:8080
Stoppen & Aufräumen:
# Stoppen (Container bleiben, Volumes bleiben)
docker compose stop
# Stoppen + Container löschen (Volumes bleiben)
docker compose down
# Alles löschen (inkl. Volumes)
docker compose down -v
Beispiel 2: LEMP-Stack (Linux, Nginx, MySQL, PHP)
Klassischer Webserver-Stack für PHP-Applikationen.
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./app:/var/www/html
depends_on:
- php
networks:
- lemp
php:
image: php:8.2-fpm
volumes:
- ./app:/var/www/html
networks:
- lemp
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: appdb
volumes:
- mysql_data:/var/lib/mysql
networks:
- lemp
volumes:
mysql_data:
networks:
lemp:
Beispiel 3: GitLab + PostgreSQL + Redis
Enterprise-Setup: GitLab benötigt Datenbank (PostgreSQL) und Cache (Redis).
version: '3.8'
services:
gitlab:
image: gitlab/gitlab-ce:latest
hostname: gitlab.example.com
ports:
- "80:80"
- "443:443"
- "22:22"
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.com'
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_host'] = 'postgres'
gitlab_rails['db_database'] = 'gitlab'
gitlab_rails['db_username'] = 'gitlab'
gitlab_rails['db_password'] = 'gitlab123'
redis['bind'] = 'redis'
volumes:
- gitlab_config:/etc/gitlab
- gitlab_logs:/var/log/gitlab
- gitlab_data:/var/opt/gitlab
depends_on:
- postgres
- redis
networks:
- gitlab_network
postgres:
image: postgres:14
environment:
POSTGRES_DB: gitlab
POSTGRES_USER: gitlab
POSTGRES_PASSWORD: gitlab123
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- gitlab_network
redis:
image: redis:alpine
networks:
- gitlab_network
volumes:
gitlab_config:
gitlab_logs:
gitlab_data:
postgres_data:
networks:
gitlab_network:
Wichtige Docker Compose Befehle
| Befehl | Beschreibung |
|---|---|
docker compose up |
Startet alle Services (foreground) |
docker compose up -d |
Startet alle Services (detached/background) |
docker compose down |
Stoppt & löscht alle Container |
docker compose down -v |
Stoppt, löscht Container + Volumes |
docker compose logs |
Zeigt Logs aller Services |
docker compose logs -f service_name |
Live-Logs eines Services |
docker compose ps |
Liste laufender Container |
docker compose exec service_name bash |
Shell in laufenden Container öffnen |
docker compose restart |
Startet alle Services neu |
docker compose pull |
Aktualisiert alle Images |
Environment-Variablen & .env-Datei
Hardcodierte Passwörter in docker-compose.yml? Schlechte Idee! Nutzen Sie .env-Dateien.
.env-Datei erstellen:
# .env
MYSQL_ROOT_PASSWORD=superGeheim123
MYSQL_DATABASE=wordpress
MYSQL_USER=wpuser
MYSQL_PASSWORD=wpPasswort456
docker-compose.yml mit Variablen:
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
Wichtig: .env zu .gitignore hinzufügen (niemals Passwörter in Git committen!)
Volumes: Daten persistent halten
Container sind ephemeral (flüchtig) – beim Löschen sind Daten weg. Volumes lösen dieses Problem.
Zwei Arten von Volumes:
1. Named Volumes (empfohlen):
volumes:
- db_data:/var/lib/mysql
Docker verwaltet Volume automatisch (Speicherort: /var/lib/docker/volumes/)
2. Bind Mounts (für Entwicklung):
volumes:
- ./my-app:/var/www/html
Lokales Verzeichnis wird direkt in Container gemountet (Änderungen sofort sichtbar).
Volume-Kommandos:
# Alle Volumes anzeigen
docker volume ls
# Volume inspizieren
docker volume inspect PROJECT_db_data
# Volume löschen (nur wenn nicht in Nutzung)
docker volume rm PROJECT_db_data
Networks: Container-Kommunikation
Docker Compose erstellt automatisch ein privates Netzwerk für alle Services. Container können sich per Service-Namen erreichen.
Beispiel: WordPress → MySQL
# WordPress-Container kann MySQL via Hostname "db" erreichen
WORDPRESS_DB_HOST: db:3306
db ist der Service-Name in docker-compose.yml → Docker-DNS löst ihn automatisch zur Container-IP auf.
Eigene Netzwerke definieren:
networks:
frontend:
backend:
services:
web:
networks:
- frontend
api:
networks:
- frontend
- backend
database:
networks:
- backend
Use Case: web kann api erreichen, aber nicht database (Security!)
Production-Ready Compose: Best Practices
1. Health Checks definieren:
services:
web:
image: nginx:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
2. Resource Limits setzen:
services:
web:
image: nginx:latest
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
memory: 256M
3. Restart Policies:
services:
web:
image: nginx:latest
restart: unless-stopped # Startet immer neu (außer manuell gestoppt)
Restart-Optionen:
no: Niemals automatisch neustartenalways: Immer neustarten (auch nach Server-Reboot)on-failure: Nur bei Fehler neustartenunless-stopped: Immer außer manuell gestoppt (empfohlen)
4. Logging konfigurieren:
services:
web:
image: nginx:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Multi-Environment Setup (Dev vs. Prod)
Gleicher Stack, unterschiedliche Configs? Nutzen Sie mehrere Compose-Dateien.
docker-compose.yml (Basis):
version: '3.8'
services:
web:
image: nginx:latest
volumes:
- ./app:/usr/share/nginx/html
docker-compose.override.yml (Dev):
version: '3.8'
services:
web:
ports:
- "8080:80"
environment:
- DEBUG=true
docker-compose.prod.yml (Production):
version: '3.8'
services:
web:
ports:
- "80:80"
restart: unless-stopped
environment:
- DEBUG=false
Starten:
# Dev (automatisch: docker-compose.yml + docker-compose.override.yml)
docker compose up -d
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Docker Compose vs. Kubernetes: Wann was?
| Kriterium | Docker Compose | Kubernetes |
|---|---|---|
| Komplexität | Niedrig (YAML-Datei) | Hoch (Manifests, Deployments, Services, Ingress) |
| Setup-Zeit | 5-15 Minuten | 2-5 Tage (für Cluster-Setup) |
| Geeignet für | 1-5 Server, Dev/Test, KMU | 10+ Server, High-Availability, Enterprise |
| Auto-Scaling | Nein | Ja (Horizontal Pod Autoscaler) |
| Self-Healing | Eingeschränkt (restart policy) | Ja (automatisches Re-Scheduling) |
| Kosten | Niedrig (Standard-Server) | Hoch (Managed K8s oder Cluster-Verwaltung) |
💡 Unsere Empfehlung
Für KMU (< 5 Server): Docker Compose ist ausreichend und deutlich einfacher.
Für Wachstum (5-10 Server): Docker Swarm (native Clustering, einfacher als Kubernetes).
Für Enterprise (> 10 Server): Kubernetes (wenn das Team die Komplexität managen kann).
Troubleshooting: Häufige Probleme
❌ Problem: "Port already in use"
Error: Bind for 0.0.0.0:80 failed: port is already allocated
Lösung: Port 80 ist bereits belegt. Ändere Port-Mapping:
ports:
- "8080:80" # Statt 80:80
❌ Problem: Container startet, aber nicht erreichbar
Diagnose:
# Container-Status prüfen
docker compose ps
# Logs anzeigen
docker compose logs service_name
# In Container einloggen
docker compose exec service_name sh
❌ Problem: Datenbank-Verbindung fehlgeschlagen
Häufigste Ursache: App startet vor Datenbank.
Lösung: depends_on + Health Check:
services:
app:
depends_on:
db:
condition: service_healthy
db:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
Checkliste: Production-Ready Docker Compose
✅ Vor Produktions-Deployment:
- ☐ Alle Passwörter in .env-Datei (nicht in docker-compose.yml)
- ☐ Restart Policy:
unless-stoppedfür alle Services - ☐ Health Checks für kritische Services
- ☐ Resource Limits (CPU/Memory) gesetzt
- ☐ Volumes für alle Daten (nicht im Container speichern!)
- ☐ Logging konfiguriert (max-size, max-file)
- ☐ Backup-Strategie für Volumes (täglich/wöchentlich)
- ☐ Monitoring (Prometheus + Grafana oder Uptime-Monitor)
- ☐ Firewall-Regeln (nur notwendige Ports öffnen)
- ☐ SSL-Terminierung (Reverse Proxy: nginx, Traefik, Caddy)
Fazit: Docker Compose für pragmatische Deployments
Docker Compose ist das ideale Tool für KMU: Einfach, schnell, pragmatisch. Mit einer YAML-Datei definieren Sie komplette Applikations-Stacks – kein Kubernetes-Overhead, keine steile Lernkurve.
Die wichtigsten Takeaways:
- ✅ Multi-Container-Apps in einer YAML-Datei definieren
- ✅
docker compose up -d→ alles läuft in Sekunden - ✅ Volumes für Persistenz (Daten überleben Container-Neustarts)
- ✅ .env-Dateien für Secrets (niemals Passwörter in Git!)
- ✅ Health Checks + Restart Policies für Produktions-Readiness
- ✅ Für KMU (< 5 Server) ist Compose ausreichend
🐳 Brauchen Sie Hilfe bei Docker & Container-Orchestrierung?
Wir unterstützen Sie bei: Docker Compose Setup, Multi-Container-Architekturen, Migration zu Docker, Kubernetes-Evaluierung, Monitoring & Backups.
Kostenlose Docker-Beratung anfragen