- 1 Section
- 10 Lessons
- unbegrenzt
- Docker & Container10
- 1.1Container vs. VM
- 1.2Docker-Architektur: Client, Daemon, Registry
- 1.3Images und Container: pull, run, stop, rm
- 1.4Dockerfile – eigene Images bauen
- 1.5Volumes: persistente Daten
- 1.6Netzwerke in Docker: bridge, host, overlay
- 1.7Docker Compose: Multi-Container-Anwendungen
- 1.8Docker in der CI/CD-Pipeline
- 1.9Sicherheit in Docker-Umgebungen
- 1.10Aufgaben Docker
Docker Compose: Multi-Container-Anwendungen
Eine moderne Anwendung besteht selten aus einem einzelnen Container. Typisch ist ein Stack aus mehreren Diensten: ein Webserver, eine API, eine Datenbank, ein Cache, vielleicht ein Message-Broker. Diese Dienste müssen mit den richtigen Konfigurationen, Volumes, Netzwerken und Abhängigkeiten gleichzeitig laufen. Jeden Container einzeln per docker run zu starten ist mühsam, fehleranfällig und nicht reproduzierbar. Hier kommt Docker Compose ins Spiel: eine YAML-Datei beschreibt den kompletten Stack, ein einziger Befehl startet alles. Compose ist das Werkzeug, mit dem aus „Docker für Einsteiger" produktive Multi-Container-Setups werden.
Die Analogie: Stell dir vor, du veranstaltest eine Dinner-Party mit fünf Gängen. Ohne Compose ist es so, als müsstest du jeden Gang einzeln bei einem anderen Restaurant bestellen, abholen, servieren – und dabei selber dafür sorgen, dass alles zur richtigen Zeit kommt, die Vorspeise vor dem Hauptgang, und der Wein zum passenden Gang. Mit Compose schreibst du das komplette Menü auf eine Karte (docker-compose.yml), gibst sie deinem Catering – und bekommst das ganze Dinner perfekt synchronisiert geliefert.
1) Anatomie einer docker-compose.yml
Eine Compose-Datei ist YAML, in der du Services, Networks und Volumes deklarierst. Klick jede Zeile, um zu sehen, was sie tut und welcher Container daraus entsteht:
web (nginx)
Port 80:80 · Bind-Mount Config · Netzwerke: frontend + backend
api (Custom Build)
DATABASE_URL=postgres://db/... · Netzwerke: backend + dbnet
db (postgres:16)
Volume db-data · Healthcheck pg_isready · Netz: dbnet
cache (redis:7-alpine)
kein Volume, kein Mapping · Netz: backend
depends_on-Beziehungen: erst db (mit Healthcheck), dann api, dann web. Die Magie steckt im Konzept „Infrastructure as Code" – siehe Infrastructure as Code.2) Die wichtigsten Compose-Direktiven
Eine Compose-Datei kennt etwa zwei Dutzend Direktiven, aber 80 % der Praxis nutzt nur eine Handvoll. Hier die wichtigsten zusammengefasst:
| Direktive | Wofür | Beispiel |
|---|---|---|
image | Image aus Registry | nginx:1.25-alpine |
build | Image aus lokalem Dockerfile bauen | ./api oder {context: ., dockerfile: Dockerfile.dev} |
ports | Port-Mapping Host:Container | - "8080:80" |
environment | Env-Variablen | DATABASE_URL: postgres://db/app |
volumes | Volume oder Bind-Mount | - db-data:/var/lib/postgresql/data |
networks | Liste der Netzwerke | [backend, dbnet] |
depends_on | Startreihenfolge / Health-Bedingung | db: {condition: service_healthy} |
restart | Auto-Restart-Policy | unless-stopped |
healthcheck | Health-Check-Befehl | test: ["CMD", "pg_isready"] |
command | Überschreibt CMD im Image | npm run dev |
env_file | Env-Variablen aus Datei laden | - .env |
deploy.resources | CPU/RAM-Limits | limits: {cpus: '1.0', memory: 512M} |
profiles | Service nur bei bestimmten Profilen aktiv | [dev, debug] |
Eine elegante Eigenschaft: Compose-Dateien sind versioniert mit der App. Sie liegen im Git-Repo, jede Code-Änderung kann mit einer passenden Infrastruktur-Änderung kommen. Das macht Compose ideal für CI/CD-Pipelines und reproduzierbare Entwicklungsumgebungen.
3) Die wichtigsten Compose-Befehle
Mit einer fertigen docker-compose.yml wird das Stack-Management zur Frage einiger weniger Kommandos:
docker-compose (mit Bindestrich, separates Tool). Seit Compose v2 ist es als Docker-Plugin integriert: docker compose (mit Leerzeichen). Beide funktionieren weiter, aber docker compose ist die moderne Form.4) Compose vs. docker run – warum es ein Unterschied ist
Was Compose deklarativ in einer YAML-Datei beschreibt, kann man theoretisch auch mit einer Reihe docker run-Befehlen umsetzen. Aber der Unterschied ist enorm:
✗ Ohne Compose (3 Container)
docker network create app-net docker volume create db-data docker run -d --name db \ --network app-net \ -v db-data:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=secret \ postgres:16 docker run -d --name cache \ --network app-net \ redis:7-alpine docker run -d --name web \ --network app-net \ -p 80:80 \ -e DB_HOST=db \ -e REDIS_HOST=cache \ myapp/web:latest
✓ Mit Compose
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
volumes:
- db-data:/var/lib/postgresql/data
cache:
image: redis:7-alpine
web:
image: myapp/web:latest
ports: ["80:80"]
environment:
DB_HOST: db
REDIS_HOST: cache
volumes:
db-data:
up kann beliebig oft aufgerufen werden, ändert nur, was geändert wurde), Dokumentierend (Datei ist gleichzeitig Dokumentation), Versionierbar (Änderungen via Git nachvollziehbar), Lesbar (YAML statt verstreuter Shell-Befehle). Für jeden Stack mit mehr als 2 Containern lohnt sich Compose.5) Profiles und Overrides – ein Stack, mehrere Konfigurationen
In der Praxis braucht ein Stack oft Variationen: in der Entwicklung läuft alles lokal, im Test mit anderen Konfigurationen, in der Produktion mit Sicherheits-Härtungen. Compose unterstützt zwei Mechanismen dafür:
Profiles: Services können einem oder mehreren Profilen zugeordnet werden. Nur Services aktiver Profile starten:
Overrides: Compose lädt automatisch docker-compose.override.yml zusätzlich zur Hauptdatei, falls vorhanden. Damit kann jeder Entwickler lokale Anpassungen machen (z. B. zusätzliche Port-Mappings, Bind-Mounts für lokalen Code), ohne die Hauptdatei zu ändern. Für CI/CD nutzt man oft docker-compose.prod.yml mit Produktions-Settings und ruft auf:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
6) Netzwerke und Service Discovery automatisch
Eines der mächtigsten Compose-Features: automatisches Networking. Sobald du docker compose up aufrufst, passiert Folgendes:
- Compose erzeugt ein default Custom-Bridge-Netzwerk (Name:
projektname_default) - Jeder Service wird automatisch an dieses Netzwerk angeschlossen
- Services können sich per Service-Namen ansprechen – wie in Custom Bridges
Im Code der API kannst du also einfach postgres://db:5432 schreiben – Compose sorgt dafür, dass db per DNS aufgelöst wird. Keine Notwendigkeit, IP-Adressen zu kennen, keine Konfigurationsdateien mit Server-Adressen.
Für komplexere Setups (wie das Beispiel oben mit frontend/backend/dbnet) kann man eigene Netzwerke deklarieren und Services darin gezielt zuordnen. Das implementiert dann saubere Netzwerksegmentierung – die DB ist nur für die API erreichbar, nicht für den Webserver.
7) Compose in der Produktion – Grenzen und Alternativen
Compose ist hervorragend für lokale Entwicklung, Test, kleine Produktionsumgebungen auf einem Server. Für größere Setups stößt es an Grenzen:
| Compose ist gut für | Compose ist NICHT geeignet für |
|---|---|
| Entwickler-Maschinen | Multi-Host-Cluster (mehrere Server) |
| Test-Umgebungen, CI-Pipelines | Auto-Scaling über Server hinweg |
| Kleine produktive Setups (1 Host) | Rolling Updates ohne Downtime |
| Demo- und Staging-Umgebungen | Hochverfügbarkeit (HA-Cluster) |
| Selbst-gehostete Apps wie Bitwarden, Nextcloud, Vaultwarden | Service Mesh, fortgeschrittene Routing-Regeln |
Für die größeren Anforderungen gibt es Kubernetes als de-facto-Standard. K8s kennt ähnliche Konzepte (Deployments, Services, Pods statt Services und Container), ist aber deutlich komplexer. Für den Übergang gibt es Tools wie kompose, die eine docker-compose.yml in Kubernetes-Manifeste übersetzen. Auch Docker Swarm ist eine Mini-Variante, die direkt aus Compose-Dateien einen Multi-Node-Cluster bauen kann – einfacher als K8s, weniger Features.
Praxis-Tipp: Wer mit Compose startet und später skalieren will, sollte schon in der Compose-Datei „K8s-kompatibel" bleiben: keine Container-IPs hardcoden, Logs an stdout/stderr ausgeben, Healthchecks definieren, Stateless-Services bauen. Damit ist die Migration zu K8s deutlich einfacher.
Zusammenfassung
Docker Compose ist das Werkzeug für Multi-Container-Anwendungen: eine docker-compose.yml deklariert Services, Networks, Volumes – ein docker compose up startet alles in der richtigen Reihenfolge. Wichtige Direktiven: image / build, ports, environment, volumes, networks, depends_on (auch mit Health-Bedingung), healthcheck, restart, profiles. Befehle: up / down / ps / logs / exec / restart / --scale. Compose erzeugt automatisch ein Custom-Bridge-Netzwerk; Services reden sich per Service-Namen an (Service Discovery). Vorteile gegenüber manuellen docker run-Befehlen: reproduzierbar, idempotent, versionierbar (Git), lesbar. Profiles und Overrides erlauben Varianten (dev/prod/debug). Grenzen: Compose ist für Single-Host gemacht – für Multi-Host-Cluster, Auto-Scaling, Rolling Updates braucht es Kubernetes oder Swarm.
Verwandte Lektionen: Docker Images & Container · Docker-Netzwerke · Docker-Volumes · und mehrWeitere relevante LektionenDockerfile schreibenDocker in CI/CDDocker-SicherheitCI/CD-Pipeline-AufbauInfrastructure as CodeNetzwerksegmentierungDatenbank-Grundlagen
