Docker Compose: Multi-Container-Anwendungen einfach definieren und starten

Moderne Webanwendungen bestehen selten aus einem einzigen Prozess. Typisch ist eine Kombination aus Applikationsserver, Datenbank und Cache – drei separate Container, die miteinander kommunizieren müssen. Mit einzelnen docker run-Befehlen wird das schnell unübersichtlich. Docker Compose löst dieses Problem: Eine einzige YAML-Datei beschreibt die gesamte Anwendungslandschaft, und mit einem Befehl wird alles gestartet.

Was ist Docker Compose?

Docker Compose ist ein Werkzeug zur Definition und Ausführung von Multi-Container-Docker-Anwendungen. Seit Docker Compose V2 ist es als Plugin direkt in die Docker CLI integriert: docker compose up (ohne Bindestrich) ist der moderne Befehl. Die Konfiguration erfolgt in einer compose.yaml- (empfohlen) oder docker-compose.yml-Datei.

Aufbau der docker-compose.yml

Eine Compose-Datei besteht aus drei Hauptabschnitten:

Häufige Muster: App + Datenbank + Cache

Das klassische Drei-Schichten-Muster sieht so aus: Eine Node.js- oder PHP-Applikation kommuniziert mit einer PostgreSQL- oder MySQL-Datenbank und nutzt Redis als Cache. In Compose wird das durch drei Service-Einträge abgebildet, die über ein gemeinsames Netzwerk miteinander verbunden sind. Der Applikationsserver kann die anderen Services direkt über ihren Service-Namen (db, cache) ansprechen – Docker Compose übernimmt die interne DNS-Auflösung.

Umgebungsvariablen

Sensible Konfiguration wie Datenbankpasswörter gehört nicht fest in die Compose-Datei. Stattdessen liest Compose automatisch eine .env-Datei im selben Verzeichnis aus. Variablen können dann als ${VARIABLE_NAME} referenziert werden. Die .env-Datei sollte niemals in ein Git-Repository eingecheckt werden.

Health Checks

Mit dem healthcheck-Schlüssel lässt sich definieren, wann ein Container als "healthy" gilt. Das ist besonders wichtig, wenn ein Service auf einen anderen warten muss – depends_on allein prüft nur, ob der Container gestartet ist, nicht ob der Dienst darin bereit ist:

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 10s
  timeout: 5s
  retries: 5
Tipp: Mit docker compose watch (verfügbar ab Compose 2.22) werden Dateiänderungen im Projektverzeichnis automatisch in den laufenden Container synchronisiert – ideal für die Entwicklung, ohne den Container neu starten zu müssen.

Praxisbeispiel: WordPress + MySQL + phpMyAdmin

Das folgende Beispiel startet einen vollständigen WordPress-Stack mit Datenbankadministration über phpMyAdmin:

services:
  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  wordpress:
    image: wordpress:latest
    restart: always
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      db:
        condition: service_healthy

  phpmyadmin:
    image: phpmyadmin:latest
    restart: always
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
    depends_on:
      - db

volumes:
  db_data:

Mit docker compose up -d startet der gesamte Stack im Hintergrund. WordPress ist danach unter http://localhost:8080, phpMyAdmin unter http://localhost:8081 erreichbar.

Vergleich: Docker Compose vs. Kubernetes vs. Podman Compose vs. Docker Swarm

Kriterium Docker Compose Kubernetes Podman Compose Docker Swarm
Zielgruppe Entwicklung & kleine Prod. Großskaliger Prod.-Betrieb Entwicklung (rootless) Kleine Prod.-Cluster
Komplexität Gering Hoch Gering Mittel
Multi-Node Nein Ja Nein Ja
Auto-Scaling Nein Ja (HPA) Nein Manuell
Root-Daemon erforderlich Ja (Docker) Nein (kubelet) Nein (rootless) Ja (Docker)
Lernkurve Sehr flach Steil Flach Moderat
Achtung: Docker Compose ist nicht für hochverfügbare Produktionssysteme auf mehreren Servern konzipiert. Sobald ein Container auf einem anderen Host laufen soll oder automatisches Failover gefordert ist, sollte zu Kubernetes oder zumindest Docker Swarm gewechselt werden.

Nützliche Compose-Befehle im Überblick

Weitere Beispiele und offizielle Compose-Spezifikation findet man in der Compose Specification.

Häufig gestellte Fragen

Was ist der Unterschied zwischen compose.yaml und docker-compose.yml?
Inhaltlich sind beide identisch. compose.yaml ist der von der Compose Specification empfohlene Dateiname. Docker Compose erkennt beide Varianten automatisch.
Kann ich Docker Compose in der Produktion einsetzen?
Für einfache Szenarien auf einem einzelnen Server ist das durchaus üblich und praktikabel. Für Multi-Server-Setups mit hoher Verfügbarkeit sollte man auf Kubernetes oder Docker Swarm ausweichen.
Wie aktualisiere ich ein einzelnes Service-Image ohne Downtime?
Mit docker compose pull <service> das neue Image herunterladen und dann docker compose up -d --no-deps <service> ausführen. Der betroffene Container wird dabei kurz neu gestartet.
Was ist Podman Compose und wann sollte ich es nutzen?
Podman Compose ist eine Alternative zu Docker Compose, die mit Podman als rootloser Container-Runtime arbeitet. Es ist besonders auf Linux-Systemen interessant, wo kein Docker-Daemon laufen soll oder darf.