Zum Hauptinhalt springen
Zurück zur Kategorie

Docker Compose Leitfaden: Verwaltung von Multi-Container-Anwendungen

Multi-Container-Anwendungen mit Docker Compose definieren und verwalten: Service-Abhängigkeiten, Umgebungsvariablen, Health Checks, Skalierung und Production-Deployment. Umfassender Leitfaden.

Lesezeit: 16 Min DevOps & Automatisierung
docker-composedockercontaineryamldevopsmicroservicedeployment
Autor
REXE Teknoloji Network & Security Team
Redaktion
REXE Teknoloji Technical Editorial
Erstveröffentlichung
Letzte Aktualisierung

Docker Compose Leitfaden: Verwaltung von Multi-Container-Anwendungen

Docker Compose ist ein Tool, mit dem Sie mehrere Docker-Container über eine einzige YAML-Datei definieren und verwalten können. Es ist unverzichtbar für Microservice-Architekturen, Webanwendungen und Entwicklungsumgebungen.

Was ist Docker Compose?

Mit Docker Compose können Sie:

  • Mehrere Services in einer einzigen docker-compose.yml-Datei definieren
  • Abhängigkeiten zwischen Services verwalten
  • Netzwerk- und Volume-Konfigurationen zentral verwalten
  • Den gesamten Stack mit einem einzigen Befehl starten/stoppen

Docker Compose v2 läuft mit dem Befehl docker compose (ohne Bindestrich) und ist in die Docker CLI integriert. Der ältere Befehl docker-compose wird weiterhin unterstützt.

Grundlegende docker-compose.yml Struktur

hljs yaml
version: '3.9'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
    restart: unless-stopped

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: geheimes_passwort
      MYSQL_DATABASE: meine_app
    volumes:
      - db_data:/var/lib/mysql
    restart: unless-stopped

volumes:
  db_data:

Services, Volumes und Networks

Services definieren

hljs yaml
services:
  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    image: meine-app:latest
    container_name: app-container
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DB_HOST: datenbank
    depends_on:
      datenbank:
        condition: service_healthy
    networks:
      - app-netzwerk
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M

Volumes definieren

hljs yaml
volumes:
  # Named Volume (von Docker verwaltet)
  db_data:
    driver: local

  # Externes Volume (bereits erstellt)
  vorhandenes_volume:
    external: true

  # Benutzerdefinierte Treiberoptionen
  nfs_volume:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.100,rw
      device: ":/nfs/freigabe"

Networks definieren

hljs yaml
networks:
  # Standard-Bridge-Netzwerk
  app-netzwerk:
    driver: bridge

  # Mit benutzerdefiniertem Subnetz
  benutzerdefiniertes-netz:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

  # Externes Netzwerk
  vorhandenes-netz:
    external: true

depends_on und Healthcheck

Kontrollieren Sie die Startreihenfolge der Services mit depends_on:

hljs yaml
services:
  web:
    image: nginx:alpine
    depends_on:
      api:
        condition: service_healthy
      db:
        condition: service_healthy

  api:
    build: ./api
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: passwort
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

depends_on kontrolliert nur die Startreihenfolge. Ohne condition: service_healthy können Sie nicht garantieren, dass der Service bereit ist.

Umgebungsvariablen und env_file

Direkte Definition

hljs yaml
services:
  app:
    image: meine-app:latest
    environment:
      - NODE_ENV=production
      - PORT=3000
      - DB_HOST=datenbank
      - DB_PORT=5432

.env-Datei verwenden

hljs yaml
services:
  app:
    image: meine-app:latest
    env_file:
      - .env
      - .env.production

.env-Datei:

hljs bash
# .env
NODE_ENV=production
DB_HOST=datenbank
DB_PORT=5432
DB_NAME=meine_app
DB_USER=benutzer
DB_PASS=geheimes_passwort
JWT_SECRET=sehr_geheimer_schluessel
REDIS_URL=redis://redis:6379

Fügen Sie .env zu .gitignore hinzu. Committen Sie niemals sensible Informationen in Git.

Skalierung (--scale)

Sie können Services mit Docker Compose horizontal skalieren:

hljs bash
# api-Service mit 3 Instanzen starten
docker compose up -d --scale api=3

# Anzahl der laufenden Instanzen ändern
docker compose up -d --scale api=5

# Bestimmten Service skalieren
docker compose scale api=3 worker=2

Load-Balancer-Konfiguration für Skalierung:

hljs yaml
services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - api

  api:
    build: ./api
    # Keine Ports definieren - nginx leitet weiter
    expose:
      - "3000"
    environment:
      NODE_ENV: production

Override-Dateien

Verwenden Sie Override-Dateien für verschiedene Umgebungen:

hljs yaml
# docker-compose.override.yml (Entwicklung)
services:
  app:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      NODE_ENV: development
    command: npm run dev

  db:
    ports:
      - "5432:5432"  # In der Entwicklung nach außen öffnen
hljs yaml
# docker-compose.prod.yml (Production)
services:
  app:
    image: registry.example.com/meine-app:latest
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1.0'
          memory: 1G

Verwendung:

hljs bash
# Entwicklung (Override wird automatisch angewendet)
docker compose up -d

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Production Best Practices

Vollständiges Production-Beispiel

hljs yaml
version: '3.9'

services:
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - certbot_data:/etc/letsencrypt:ro
    depends_on:
      - api
    restart: always
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  api:
    image: registry.example.com/api:${APP_VERSION:-latest}
    env_file: .env.production
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    restart: always
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M

  db:
    image: postgres:15-alpine
    env_file: .env.production
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    restart: always
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  postgres_data:
  redis_data:
  certbot_data:

Wichtige Befehle

hljs bash
# Alle Services starten
docker compose up -d

# Bestimmten Service starten
docker compose up -d api

# Logs verfolgen
docker compose logs -f
docker compose logs -f api

# Services stoppen
docker compose down

# Services stoppen und Volumes löschen
docker compose down -v

# Service neu starten
docker compose restart api

# Service-Status anzeigen
docker compose ps

# Befehl in Service ausführen
docker compose exec api bash

# Images neu erstellen
docker compose build --no-cache
docker compose up -d --build

# Konfiguration validieren
docker compose config

Fazit

Docker Compose ist der praktischste Weg, Multi-Container-Anwendungen zu verwalten. Es bietet eine konsistente Umgebung von der Entwicklung bis zur Production. Mit Override-Dateien können Sie verschiedene Umgebungen flexibel konfigurieren, und mit Healthcheck und depends_on können Sie Service-Abhängigkeiten sicher verwalten.

Häufig gestellte Fragen

Was macht der Befehl docker compose config?

'docker compose config' zeigt die endgültige Konfiguration nach Anwendung aller Override-Dateien und Umgebungsvariablen. Es ist nützlich zum Debuggen und zur Überprüfung der Konfiguration.

Ich verwende depends_on, aber mein Service versucht sich zu verbinden, bevor die Abhängigkeit bereit ist. Warum?

'depends_on' wartet standardmäßig nur darauf, dass der Container startet, nicht darauf, dass er bereit ist. Verwenden Sie 'condition: service_healthy', um zu warten, bis der Healthcheck bestanden wird. Es wird auch empfohlen, Retry-Logik in Ihrer Anwendung hinzuzufügen.

Ist es sinnvoll, Docker Compose in der Production zu verwenden?

Docker Compose eignet sich für Single-Server-Deployments. Wenn Sie Multi-Server-Orchestrierung benötigen, wird Kubernetes oder Docker Swarm bevorzugt. Docker Compose wird in der Production für kleine bis mittelgroße Anwendungen häufig eingesetzt.

Wie werden Variablen aus der .env-Datei in docker-compose.yml verwendet?

Docker Compose liest die .env-Datei im selben Verzeichnis automatisch. Greifen Sie mit der Syntax '${VARIABLE_NAME}' auf Werte zu. Zum Beispiel: 'image: myapp:${APP_VERSION:-latest}'. Verwenden Sie ':-' für Standardwerte.

Wie verhindere ich Port-Konflikte beim Skalieren von Services?

Verwenden Sie 'expose' statt 'ports' für skalierte Services. Expose öffnet den Port nur für das interne Netzwerk. Leiten Sie externen Traffic über einen Load Balancer (nginx, traefik) weiter. So können mehrere Instanzen denselben internen Port verwenden.

Was ist der Unterschied zwischen docker compose down und docker compose stop?

'docker compose stop' stoppt Container, entfernt sie aber nicht. 'docker compose down' stoppt und entfernt Container. Mit dem Flag '-v' werden auch Volumes gelöscht. 'stop' wird für die Entwicklung empfohlen, 'down' sollte in der Production vorsichtig verwendet werden.

Verwandte Artikel

Server-Automatisierung mit Ansible: Infrastructure as Code

Ansible-Installation, Inventory-Datei, Playbook-Erstellung, Rollenstruktur, Variablen, verschlüsselter Vault, Ad-hoc-Befehle und Server-Konfigurationsautomatisierung. Schritt-für-Schritt-Anleitung.

20 Min
ansibleautomatisierunginfrastructure as code
NetzwerkverkehrEingehend GbpsAusgehend Gbps