Docker Tutorial #6: Docker Compose – Multi-Container-Anwendungen einfach verwalten
Was ist Docker Compose?
Docker Compose ist ein Tool zur Definition und Verwaltung von Multi-Container-Anwendungen. Mit einer einzigen YAML-Datei können Sie alle Services Ihrer Anwendung konfigurieren und mit einem Befehl starten.
Ohne Compose:
docker network create mein-netz
docker run -d --name db --network mein-netz mysql
docker run -d --name app --network mein-netz -p 80:80 myapp
docker run -d --name redis --network mein-netz redis
Mit Compose:
docker compose up -d
Installation prüfen
Docker Compose ist in Docker Desktop bereits enthalten:
docker compose version
Ausgabe: Docker Compose version v2.x.x
Ihre erste docker-compose.yml
Erstellen Sie docker-compose.yml:
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
Erstellen Sie html/index.html:
<h1>Docker Compose funktioniert!</h1>
Starten:
docker compose up -d
Besuchen Sie http://localhost:8080
Stoppen:
docker compose down
Struktur einer docker-compose.yml
version: '3.8' # Compose-Version
services: # Container-Definitionen
service1: # Service-Name
image: # Docker-Image
build: # Build-Konfiguration
ports: # Port-Mappings
volumes: # Volume-Mounts
environment: # Umgebungsvariablen
depends_on: # Abhängigkeiten
networks: # Netzwerke
volumes: # Named Volumes
networks: # Custom Networks
Beispiel: WordPress mit MySQL
version: '3.8'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: geheim
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
volumes:
- db_data:/var/lib/mysql
restart: always
wordpress:
image: wordpress:latest
depends_on:
- db
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html
restart: always
volumes:
db_data:
wp_data:
Starten:
docker compose up -d
WordPress ist unter http://localhost:8080 erreichbar.
Eigenes Image bauen
version: '3.8'
services:
app:
build: . # Dockerfile im aktuellen Verzeichnis
ports:
- "3000:3000"
# Oder mit Optionen:
app2:
build:
context: . # Build-Kontext
dockerfile: Dockerfile.dev # Alternatives Dockerfile
args:
- NODE_ENV=development # Build-Argumente
ports:
- "3001:3000"
Wichtige Service-Optionen
Ports
services:
web:
ports:
- "8080:80" # HOST:CONTAINER
- "443:443"
- "127.0.0.1:3000:3000" # Nur localhost
Volumes
services:
app:
volumes:
- ./code:/app # Bind Mount
- /app/node_modules # Anonymes Volume
- data:/app/data # Named Volume
- ./config.json:/app/config.json:ro # Read-only
Environment Variables
services:
app:
environment:
NODE_ENV: production
PORT: 3000
DB_HOST: mysql
# Oder aus Datei:
env_file:
- .env
- .env.local
Restart Policy
services:
app:
restart: always # Immer neu starten
# restart: unless-stopped # Außer manuell gestoppt
# restart: on-failure # Nur bei Fehler
# restart: no # Nie (Standard)
Depends On
services:
app:
depends_on:
- db
- redis
db:
image: mysql:8.0
redis:
image: redis:alpine
Praktisches Beispiel: LEMP-Stack
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./app:/var/www/html
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- php
networks:
- app-network
php:
build:
context: ./php
dockerfile: Dockerfile
volumes:
- ./app:/var/www/html
networks:
- app-network
depends_on:
- mysql
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
MYSQL_USER: user
MYSQL_PASSWORD: password
volumes:
- mysql_data:/var/lib/mysql
networks:
- app-network
phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- "8080:80"
environment:
PMA_HOST: mysql
PMA_PORT: 3306
depends_on:
- mysql
networks:
- app-network
volumes:
mysql_data:
networks:
app-network:
driver: bridge
Docker Compose Befehle
Starten und Stoppen
# Alle Services starten
docker compose up
# Im Hintergrund
docker compose up -d
# Mit Rebuild
docker compose up -d --build
# Nur bestimmte Services
docker compose up -d nginx mysql
# Services stoppen
docker compose stop
# Services stoppen und entfernen
docker compose down
# Mit Volumes löschen
docker compose down -v
# Mit Images löschen
docker compose down --rmi all
Logs und Monitoring
# Logs aller Services
docker compose logs
# Logs verfolgen
docker compose logs -f
# Bestimmter Service
docker compose logs -f app
# Letzte 100 Zeilen
docker compose logs --tail=100
# Status anzeigen
docker compose ps
# Detaillierte Infos
docker compose ps -a
# Ressourcen-Verbrauch
docker compose top
Build und Update
# Images neu bauen
docker compose build
# Ohne Cache
docker compose build --no-cache
# Bestimmten Service
docker compose build app
# Pull neue Images
docker compose pull
# Services neu starten
docker compose restart
# Einzelnen Service
docker compose restart api
In Container einsteigen
# Bash öffnen
docker compose exec app bash
# Befehl ausführen
docker compose exec app php artisan migrate
# Als root
docker compose exec -u root app bash
# Neuer Container für einmaligen Befehl
docker compose run --rm app npm install
Umgebungsvariablen
.env-Datei
Erstellen Sie .env:
DB_PASSWORD=geheim123
DB_NAME=meinedatenbank
APP_PORT=8080
NODE_ENV=production
Verwenden in docker-compose.yml:
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
ports:
- "${APP_PORT}:3306"
Mehrere Umgebungen
# docker-compose.yml (Basis)
services:
app:
image: myapp
ports:
- "8080:3000"
# docker-compose.override.yml (Development)
services:
app:
build: .
volumes:
- .:/app
environment:
- NODE_ENV=development
# docker-compose.prod.yml (Production)
services:
app:
environment:
- NODE_ENV=production
restart: always
Development:
docker compose up -d
Production:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Netzwerke
Default Network
Compose erstellt automatisch ein Netzwerk. Services können sich über ihren Namen erreichen:
services:
api:
image: myapi
db:
image: mysql
In api ist db unter dem Hostname db erreichbar.
Custom Networks
services:
frontend:
image: nginx
networks:
- frontend-net
backend:
image: myapi
networks:
- frontend-net
- backend-net
database:
image: mysql
networks:
- backend-net
networks:
frontend-net:
backend-net:
Frontend kann nur auf Backend zugreifen, nicht auf Datenbank.
Volumes im Detail
volumes:
# Named Volume (empfohlen)
mysql_data:
driver: local
# Mit Optionen
app_data:
driver: local
driver_opts:
type: none
device: /path/on/host
o: bind
# Externe Volume
existing_data:
external: true
Skalierung
# 3 Instanzen eines Services
docker compose up -d --scale api=3
# Load Balancing mit Nginx
docker compose up -d --scale api=5
Für Load Balancing benötigen Sie zusätzliche Konfiguration.
Beispiel: Shopware 6 Development
version: '3.8'
services:
app:
build:
context: .
dockerfile: docker/Dockerfile
volumes:
- .:/var/www/html
- /var/www/html/vendor
- /var/www/html/var
environment:
DATABASE_URL: mysql://shopware:shopware@mysql:3306/shopware
APP_URL: http://localhost:8000
depends_on:
- mysql
- redis
webserver:
image: nginx:alpine
ports:
- "8000:80"
volumes:
- .:/var/www/html
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
mysql:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: shopware
MYSQL_USER: shopware
MYSQL_PASSWORD: shopware
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
ports:
- "6379:6379"
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
adminer:
image: adminer
ports:
- "8080:8080"
volumes:
mysql_data:
Best Practices
- Version Pinning: Keine
latestTags - Named Volumes: Für persistente Daten
- Health Checks: Für kritische Services
- .env verwenden: Keine Secrets im Code
- Netzwerk-Isolation: Services trennen
- Restart Policies: Für Production
- Ressourcen-Limits: CPU/Memory begrenzen
Troubleshooting
# Detaillierter Output
docker compose up --verbose
# Services neu erstellen
docker compose up -d --force-recreate
# Netzwerk-Probleme
docker compose down
docker compose up -d
# Volumes-Probleme
docker compose down -v
docker compose up -d
Zusammenfassung
- Compose verwaltet Multi-Container-Apps
- Eine YAML-Datei für alle Services
- Einfache Befehle: up, down, logs
- Perfekt für Entwicklung und Testing
- Production-ready mit richtiger Konfiguration

Author: Andreas Lang
Andreas Lang konzentriert sich seit zwei Jahrzehnten auf die Webentwicklung und Webdesign mit dem Schwerpunkt PHP, Laravel und Javascript und betreut seine Kunden mit Herz und Seele in allen Bereichen von Entwicklung, Design, Suchmaschinenoptimierung, IT-Recht, IT-Sicherheit etc.

