Docker

0 58

Das Problem: Container sind temporär

Wenn Sie einen Container löschen, verschwinden alle Daten darin:

docker run -d --name mysql1 -e MYSQL_ROOT_PASSWORD=test mysql:8.0
# Datenbank nutzen, Daten erstellen...
docker rm -f mysql1
# Alle Daten sind weg! ❌

Lösung: Docker Volumes

Was sind Volumes?

Volumes sind Docker-verwaltete Speicherbereiche außerhalb des Container-Dateisystems. Daten in Volumes bleiben erhalten, auch wenn Container gelöscht werden.

Drei Arten von Volume-Mounts

  1. Named Volumes (empfohlen)
  2. Bind Mounts (Development)
  3. tmpfs Mounts (temporär)

Named Volumes

Docker verwaltet die Volumes automatisch unter /var/lib/docker/volumes/.

Volume erstellen

# Volume erstellen
docker volume create mysql-data

# Volume verwenden
docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=geheim \
  mysql:8.0

Volume-Befehle

# Alle Volumes anzeigen
docker volume ls

# Volume-Details
docker volume inspect mysql-data

# Volume löschen
docker volume rm mysql-data

# Alle ungenutzten Volumes löschen
docker volume prune

Vorteile Named Volumes

✅ Docker verwaltet Speicherort
✅ Einfach zu sichern
✅ Funktioniert auf allen Plattformen
✅ Bessere Performance als Bind Mounts
✅ Kann zwischen Containern geteilt werden

Praxisbeispiel: MySQL mit persistenten Daten

# Volume erstellen
docker volume create mysql-production

# MySQL starten
docker run -d \
  --name mysql-prod \
  -v mysql-production:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=sicher123 \
  -e MYSQL_DATABASE=meineshop \
  -p 3306:3306 \
  mysql:8.0

# Daten hinzufügen...
# Container löschen
docker rm -f mysql-prod

# Neuen Container mit denselben Daten
docker run -d \
  --name mysql-prod-2 \
  -v mysql-production:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.0

# Daten sind wieder da! ✅

Bind Mounts

Bind Mounts verknüpfen ein Host-Verzeichnis direkt mit einem Container-Verzeichnis. Ideal für Development.

Syntax

docker run -v /host/pfad:/container/pfad image
# Oder modern:
docker run --mount type=bind,source=/host/pfad,target=/container/pfad image

Praxisbeispiel: PHP-Entwicklung

# Aktuelles Verzeichnis mounten
docker run -d \
  --name php-dev \
  -v $(pwd):/var/www/html \
  -p 8080:80 \
  php:8.2-apache

# Code-Änderungen sind sofort sichtbar!

Read-Only Mounts

# Nur lesend mounten
docker run -v $(pwd)/config:/app/config:ro nginx

Vorteile Bind Mounts

✅ Direkter Zugriff auf Host-Dateisystem
✅ Echtzeit-Synchronisation
✅ Perfekt für Development
✅ Code-Änderungen sofort verfügbar

⚠️ Nachteile:

  • Performance-Probleme auf Windows/Mac
  • Pfad-Abhängigkeiten
  • Sicherheitsrisiko (Container sieht Host-Dateien)

tmpfs Mounts

Temporärer Speicher im RAM. Daten verschwinden beim Container-Stopp.

docker run -d \
  --name app \
  --tmpfs /tmp \
  --tmpfs /run \
  myapp

Verwendung:

  • Sensible temporäre Daten
  • Session-Speicher
  • Cache

Docker Compose mit Volumes

Named Volumes

version: '3.8'

services:
  db:
    image: mysql:8.0
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: geheim

  redis:
    image: redis:alpine
    volumes:
      - redis_data:/data

volumes:
  mysql_data:
  redis_data:

Bind Mounts für Development

version: '3.8'

services:
  app:
    build: .
    volumes:
      # Source Code
      - ./src:/app/src
      
      # Config
      - ./config.json:/app/config.json:ro
      
      # Node modules nicht überschreiben
      - /app/node_modules
    ports:
      - "3000:3000"

Volume mit Optionen

volumes:
  mysql_data:
    driver: local
    driver_opts:
      type: none
      device: /mnt/storage/mysql
      o: bind

Volumes teilen zwischen Containern

# Container 1: Erstellt Daten
docker run -d \
  --name producer \
  -v shared-data:/data \
  alpine sh -c "echo 'Hallo' > /data/nachricht.txt; sleep 3600"

# Container 2: Liest Daten
docker run --rm \
  -v shared-data:/data \
  alpine cat /data/nachricht.txt
# Ausgabe: Hallo ✅

Volumes sichern und wiederherstellen

Backup erstellen

# Volume sichern
docker run --rm \
  -v mysql-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/mysql-backup.tar.gz /data

Backup wiederherstellen

# Neues Volume erstellen
docker volume create mysql-data-neu

# Backup einspielen
docker run --rm \
  -v mysql-data-neu:/data \
  -v $(pwd):/backup \
  alpine sh -c "cd /data && tar xzf /backup/mysql-backup.tar.gz --strip 1"

Automatisiertes Backup-Script

#!/bin/bash
# backup-volumes.sh

BACKUP_DIR="./backups"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Alle Volumes sichern
for volume in $(docker volume ls -q); do
  echo "Sichere $volume..."
  docker run --rm \
    -v $volume:/data \
    -v $BACKUP_DIR:/backup \
    alpine tar czf /backup/${volume}_${DATE}.tar.gz /data
done

echo "Backup abgeschlossen!"

Volume von einem Container zu anderem migrieren

# Container 1 Daten
docker run -d --name old-app -v data:/data alpine sleep 3600

# Daten zu neuem Container
docker run -d --name new-app -v data:/data alpine sleep 3600

# Daten sind verfügbar! ✅

Praktisches Beispiel: WordPress-Upgrade

version: '3.8'

services:
  wordpress:
    image: wordpress:6.4-php8.2
    ports:
      - "8080:80"
    volumes:
      - wp_content:/var/www/html/wp-content
      - wp_uploads:/var/www/html/wp-content/uploads
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass

  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass
      MYSQL_ROOT_PASSWORD: root

volumes:
  wp_content:
  wp_uploads:
  db_data:

Upgrade:

# Aktuelle Version
docker compose up -d

# Später: Neue WordPress-Version
# Ändern Sie im docker-compose.yml:
# image: wordpress:6.5-php8.3

# Upgrade durchführen
docker compose down
docker compose up -d

# Daten bleiben erhalten! ✅

Volume-Performance optimieren

Delegated Mounts (macOS/Windows)

services:
  app:
    volumes:
      # Schneller auf macOS/Windows
      - ./src:/app/src:delegated

Modi:

  • consistent: Sync (langsam, aber konsistent)
  • cached: Host → Container verzögert
  • delegated: Container → Host verzögert (schnellste Option)

Volumes vs. Bind Mounts Performance

Linux:

  • Beide ähnlich schnell

macOS/Windows:

  • Named Volumes: ~5x schneller als Bind Mounts
  • Für große Code-Basen: Besser Named Volumes + rsync

Externe Volumes

Volumes, die außerhalb von Compose existieren:

volumes:
  shared_data:
    external: true

Erstellen:

docker volume create shared_data

Volume-Treiber

NFS-Volume

volumes:
  nfs_data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.100,rw
      device: ":/mnt/nfs_share"

CIFS/SMB-Volume (Windows-Share)

volumes:
  smb_data:
    driver: local
    driver_opts:
      type: cifs
      o: username=user,password=pass
      device: "//192.168.1.100/share"

Best Practices

1. Named Volumes für Daten

# ✅ Gut
volumes:
  - db_data:/var/lib/mysql

# ❌ Schlecht (Daten gehen bei Rebuild verloren)
# Keine Volume-Definition

2. .dockerignore für Bind Mounts

node_modules
.git
*.log
.env

3. Volumes dokumentieren

volumes:
  mysql_data:
    # Produktions-Datenbank
    # Täglich um 3 Uhr gesichert
    driver: local

4. Regelmäßige Backups

# Cron-Job täglich um 3 Uhr
0 3 * * * /home/user/backup-volumes.sh

5. Volumes aufräumen

# Wöchentlich ungenutzte Volumes löschen
docker volume prune -f

Troubleshooting

Volume ist nicht leer

# Volume-Inhalt anzeigen
docker run --rm -v volume-name:/data alpine ls -la /data

Berechtigungsprobleme

# Als bestimmter User ausführen
docker run --rm \
  -v $(pwd):/data \
  -u $(id -u):$(id -g) \
  alpine chown -R $(id -u):$(id -g) /data

Volume-Größe prüfen

# Größe aller Volumes
docker system df -v

# Einzelnes Volume
docker run --rm -v volume-name:/data alpine du -sh /data

Zusammenfassung

  • Named Volumes: Für Produktions-Daten
  • Bind Mounts: Für Development
  • tmpfs: Für temporäre Daten
  • Immer Volumes für persistente Daten
  • Regelmäßige Backups durchführen
  • Volume-Performance beachten

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.