Docker Compose Fortgeschritten: Profiles, Overrides & Healthchecks
Mehrere Umgebungen, optionale Services und stabile Startreihenfolgen mit Compose: Profiles, Override-Dateien, depends_on mit Healthcheck-Conditions, Secrets, Watch-Mode und YAML-Anchors.
Zuletzt aktualisiert: 12. Mai 2026
docker-compose-basics hat dir gezeigt, wie du mehrere Container in
einer docker-compose.yml zusammenführst. Sobald aber Dev, Test
und Prod ins selbe Repo wollen — oder bestimmte Services nur
manchmal laufen sollen — brauchst du die Werkzeuge aus diesem Kurs.
Lernziele
- Du strukturierst Compose-Setups mit Profiles und Override-Dateien
- Du startest Services in der richtigen Reihenfolge dank Healthchecks
- Du nutzt Secrets, Watch-Mode und YAML-Anchors sinnvoll
- Du verstehst, wann Compose endet und Kubernetes anfängt
Profiles — optionale Services
Manche Services sollen nicht immer starten — Tools wie pgadmin,
ein Mock-SMTP-Server oder Lasttests sind nur situativ nötig.
services:
api:
image: myapp:dev
db:
image: postgres:16
pgadmin:
image: dpage/pgadmin4
profiles: ["tools"]
loadtest:
image: grafana/k6
profiles: ["perf"]docker compose up # nur api + db
docker compose --profile tools up # api + db + pgadmin
docker compose --profile perf up # api + db + loadtestEin Service kann auch zu mehreren Profilen gehören. Ohne Profil
gestartet wird er nur, wenn das Profil aktiv ist oder ein anderer
Service ihn als depends_on referenziert.
Override-Dateien
Compose liest automatisch zwei Dateien: docker-compose.yml und —
wenn vorhanden — docker-compose.override.yml. Die zweite ergänzt /
überschreibt die erste.
# docker-compose.yml — Basis für alle
services:
api:
image: myapp
environment:
NODE_ENV: production# docker-compose.override.yml — nur Dev, lokal nicht committen
services:
api:
build: .
environment:
NODE_ENV: development
volumes:
- ./src:/app/src
command: npm run devFür andere Umgebungen explizit:
docker compose -f docker-compose.yml -f docker-compose.prod.yml upflowchart LR
Base[docker-compose.yml]
Override[docker-compose.override.yml<br/><small>auto, lokal</small>]
Prod[docker-compose.prod.yml<br/><small>explizit</small>]
Test[docker-compose.test.yml<br/><small>explizit, CI</small>]
Base --> Effective[Effektives Setup]
Override -. "dev (default)" .-> Effective
Prod -. "-f prod.yml" .-> Effective
Test -. "-f test.yml" .-> EffectiveKonvention:
docker-compose.override.ymlin.gitignorelassen. Eine Vorlage alsdocker-compose.override.yml.examplecommitten.
Healthchecks + depends_on mit Condition
depends_on allein wartet nur, bis der Prozess gestartet ist —
nicht, bis der Service bereit ist. Mit Healthcheck-Conditions geht
es richtig:
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 10
start_period: 5s
api:
image: myapp
depends_on:
db:
condition: service_healthycondition |
Bedeutung |
|---|---|
service_started |
Default — nur „läuft" |
service_healthy |
Wartet auf grünen Healthcheck |
service_completed_successfully |
Für One-Shot-Jobs (Migration) |
Migrations-Pattern: Ein
migrate-Service mitrestart: "no"läuft einmal, undapiwartet mitservice_completed_successfullydarauf.
Secrets in Compose
Niemals Secrets in environment: schreiben (die landen in docker inspect, Logs, Histories). Mit Compose-Secrets bekommen sie als Datei
in den Container:
services:
api:
image: myapp
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txtDie App liest dann /run/secrets/db_password. Im Dev-Workflow kann die
Datei lokal liegen; in Prod kommen die Secrets aus Vault / SOPS / Env.
YAML-Anchors für DRY-Configs
Mehrere ähnliche Services? Anchors (&) und Aliase (*) helfen:
x-defaults: &api-defaults
image: myapp:dev
environment:
NODE_ENV: development
depends_on:
- db
services:
api-eu:
<<: *api-defaults
environment:
REGION: eu
api-us:
<<: *api-defaults
environment:
REGION: usDer x--Prefix sorgt dafür, dass Compose den Block ignoriert — er ist
nur ein Anchor-Container.
Compose Watch — Hot-Reload ohne Bind-Mounts
Statt das ganze Quellverzeichnis in den Container zu mounten (was auf macOS/Windows langsam ist), kann Compose Dateiänderungen erkennen und gezielt reagieren:
services:
web:
build: .
develop:
watch:
- action: sync
path: ./src
target: /app/src
- action: rebuild
path: ./package.jsondocker compose watchErgebnis: schneller, plattform-unabhängiger, und der package.json-
Change löst automatisch einen Rebuild aus.
Resource Limits
Compose kennt deploy.resources (auch ohne Swarm):
services:
api:
image: myapp
deploy:
resources:
limits:
cpus: "1.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 128MPraktisch, um lokal realistische Bedingungen zu testen — bevor du in Kubernetes feststellst, dass deine App 800 MB zieht.
Networks — gezielt segmentieren
Standard: Compose erzeugt ein Netzwerk pro Projekt. Mehrere Netzwerke helfen, Services voneinander zu isolieren:
services:
api:
networks: [frontend, backend]
web:
networks: [frontend]
db:
networks: [backend] # nicht von web erreichbar
networks:
frontend:
backend:Ein externes Netzwerk teilen (z. B. mit einem zweiten Compose-Projekt):
networks:
shared:
external: trueCompose in CI
Compose ist auch in der CI nützlich — für Integrationstests gegen echte Abhängigkeiten:
# docker-compose.test.yml
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: ci
tmpfs: /var/lib/postgresql/data # schneller, flüchtig
tests:
build: .
command: npm test
depends_on:
db:
condition: service_healthydocker compose -f docker-compose.test.yml run --rm testsrun --rm startet den tests-Service einmalig und räumt auf — perfekt
für CI-Pipelines.
Häufige Stolperfallen
„depends_on startet trotzdem zu früh"
Du hast service_started (Default) statt service_healthy — und der
DB-Container braucht 4 Sekunden bis Postgres lauscht. Healthcheck +
Condition setzen.
„Mein Override greift nicht"
docker compose config ausführen — das zeigt das effektive
Resultat aller Dateien zusammen. Häufig: falsche Verschachtelung oder
ein Tippfehler im Service-Namen.
„Volumes überleben Neustarts nicht"
Wahrscheinlich ein Bind-Mount statt Named Volume, oder
docker compose down -v wurde aufgerufen (löscht Volumes explizit).
„Profile-Service startet, obwohl ich ihn nicht will"
Ein anderer Service hat ihn als depends_on. Profile deaktivieren
einen Service nicht hart — sie schließen ihn nur aus der automatischen
Auswahl aus.
Wo Compose endet, Kubernetes anfängt
Compose ist für einen Host gedacht. Brauchst du Ausfallsicherheit über mehrere Maschinen, Autoscaling, Rollouts, Self-Healing über Host- Grenzen hinweg — dann ist es Zeit für Kubernetes (siehe nächste Kursreihe).
| Feature | Compose | Kubernetes |
|---|---|---|
| Single-Host Orchestrierung | Stark | Möglich, aber overkill |
| Multi-Host Scheduling | Nein | Kernfeature |
| Self-Healing / Replicas | Begrenzt | Kernfeature |
| Lokale Entwicklung | Top | Mit Kind/Minikube ok |
| Lernkurve | Flach | Steil |
Praxis-Übung
Erweitere ein bestehendes Compose-Setup:
- Lege ein
tools-Profile an (z. B.pgadminoderredis-commander). - Splitte in
docker-compose.yml(Basis) unddocker-compose.override.yml(Dev). - Ergänze einen Healthcheck für die Datenbank und
condition: service_healthyan einem abhängigen Service. - Verschiebe ein Passwort aus
environmentin einen Compose-Secret. - Probier
docker compose watchstatt klassischer Bind-Mounts.
Weiterführendes
- Compose Specification: https://compose-spec.io/
- Compose Watch: https://docs.docker.com/compose/file-watch/
depends_onConditions: https://docs.docker.com/compose/startup-order/- Compose vs. Kubernetes: https://kompose.io/ (Konverter, gut zum Lernen)