Docker

0 57

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

  1. Version Pinning: Keine latest Tags
  2. Named Volumes: Für persistente Daten
  3. Health Checks: Für kritische Services
  4. .env verwenden: Keine Secrets im Code
  5. Netzwerk-Isolation: Services trennen
  6. Restart Policies: Für Production
  7. 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

Sphinx-Flashdesign.de

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.