Container sind flüchtig - beim Löschen verschwinden alle Daten. Docker-Volumes lösen dieses Problem und ermöglichen persistente Datenspeicherung.

Warum Volumes?

Ohne Volumes gehen Daten verloren bei:

  • Container-Neuerstellung
  • Image-Updates
  • docker rm

Mit Volumes bleiben Daten erhalten:

  • Datenbanken
  • Uploads
  • Konfigurationen
  • Logs

Arten der Datenspeicherung

1. Volumes (empfohlen)

Von Docker verwaltet, in /var/lib/docker/volumes/:

docker volume create mein-volume
docker run -v mein-volume:/app/data nginx

2. Bind Mounts

Host-Verzeichnis direkt einbinden:

docker run -v /host/pfad:/container/pfad nginx

3. tmpfs Mounts

Im RAM, nicht persistent:

docker run --tmpfs /app/cache nginx

Volumes erstellen und verwalten

Volume erstellen

docker volume create mein-volume

Volumes auflisten

docker volume ls

Volume-Details

docker volume inspect mein-volume

Volume löschen

docker volume rm mein-volume

Ungenutzte Volumes löschen

docker volume prune

Volumes in Containern nutzen

Mit -v Flag

docker run -d \
  --name mysql-db \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=geheim \
  mysql:8

Mit --mount (moderner)

docker run -d \
  --name mysql-db \
  --mount source=mysql-data,target=/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=geheim \
  mysql:8

Readonly-Volume

docker run -d \
  -v config-vol:/etc/config:ro \
  nginx

Bind Mounts

Host-Verzeichnis einbinden

docker run -d \
  -v /var/www/html:/usr/share/nginx/html \
  nginx

Mit absolutem Pfad (Pflicht)

# Richtig
docker run -v /home/user/app:/app nginx

# Falsch (wird als Volume-Name interpretiert)
docker run -v ./app:/app nginx

Für Entwicklung ideal

docker run -d \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/config:/app/config \
  node:18

Docker Compose

Volumes in docker-compose.yml

version: '3.8'

services:
  db:
    image: mysql:8
    volumes:
      - mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: geheim

  web:
    image: wordpress
    volumes:
      - wp-content:/var/www/html/wp-content
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
    depends_on:
      - db

volumes:
  mysql-data:
  wp-content:

Benannte vs. anonyme Volumes

volumes:
  # Benannt (empfohlen)
  mysql-data:

  # Mit Optionen
  nfs-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=10.0.0.1,rw
      device: ":/data"

Externe Volumes

volumes:
  existing-volume:
    external: true

Backup von Volumes

Mit tar

docker run --rm \
  -v mysql-data:/data \
  -v $(pwd):/backup \
  ubuntu tar cvf /backup/mysql-backup.tar /data

Direkt aus Volume-Verzeichnis

# Volume-Pfad finden
docker volume inspect mysql-data --format '{{ .Mountpoint }}'

# Backup erstellen
tar -czvf backup.tar.gz /var/lib/docker/volumes/mysql-data/_data

Volume klonen

docker volume create new-volume
docker run --rm \
  -v mysql-data:/from \
  -v new-volume:/to \
  ubuntu bash -c "cp -av /from/* /to/"

Volume-Daten wiederherstellen

docker run --rm \
  -v mysql-data:/data \
  -v $(pwd):/backup \
  ubuntu bash -c "cd /data && tar xvf /backup/mysql-backup.tar --strip 1"

Praktische Beispiele

WordPress mit Volumes

version: '3.8'

services:
  wordpress:
    image: wordpress
    ports:
      - "80:80"
    volumes:
      - wp-files:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_PASSWORD: geheim

  db:
    image: mysql:8
    volumes:
      - db-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: geheim
      MYSQL_DATABASE: wordpress

volumes:
  wp-files:
  db-data:

Nextcloud mit Volumes

version: '3.8'

services:
  nextcloud:
    image: nextcloud
    volumes:
      - nextcloud-data:/var/www/html
      - nextcloud-apps:/var/www/html/custom_apps
      - nextcloud-config:/var/www/html/config
    ports:
      - "8080:80"

volumes:
  nextcloud-data:
  nextcloud-apps:
  nextcloud-config:

Entwicklungsumgebung

version: '3.8'

services:
  app:
    build: .
    volumes:
      # Code live ändern
      - ./src:/app/src
      # node_modules im Volume (schneller)
      - node_modules:/app/node_modules
    ports:
      - "3000:3000"

volumes:
  node_modules:

Volume-Treiber

Lokaler Treiber (Standard)

docker volume create --driver local mein-volume

NFS-Volume

docker volume create \
  --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.1,rw \
  --opt device=:/shared \
  nfs-volume

In Compose

volumes:
  nfs-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=192.168.1.1,rw,nfsvers=4
      device: ":/shared"

tmpfs für temporäre Daten

docker run -d \
  --tmpfs /app/cache:size=100m \
  nginx

In Compose:

services:
  app:
    image: nginx
    tmpfs:
      - /app/cache:size=100m

Best Practices

1. Volumes für persistente Daten

volumes:
  - db-data:/var/lib/mysql     # Richtig

Nicht:

volumes:
  - ./mysql-data:/var/lib/mysql  # Bind Mount für Datenbank = Probleme

2. Bind Mounts für Entwicklung

volumes:
  - ./src:/app/src  # Code-Änderungen live

3. Separate Volumes für verschiedene Daten

volumes:
  - mysql-data:/var/lib/mysql
  - mysql-logs:/var/log/mysql
  - mysql-conf:/etc/mysql/conf.d

4. Backup-Strategie

  • Regelmäßige Volume-Backups
  • Vor Updates/Upgrades sichern
  • Backup-Integrität testen

Troubleshooting

Permission-Probleme

# User-ID im Container prüfen
docker exec container-name id

# Volume mit korrektem User erstellen
docker run --rm \
  -v mein-volume:/data \
  ubuntu chown -R 1000:1000 /data

Volume nicht beschreibbar

# Prüfen ob :ro gesetzt
docker inspect container-name | grep -A5 Mounts

# Ohne :ro neu starten
docker run -v volume:/data nginx

Volume-Daten finden

docker volume inspect volume-name --format '{{ .Mountpoint }}'

Fazit

Volumes sind essenziell für produktive Docker-Umgebungen. Nutzen Sie benannte Volumes für Datenbanken und persistente Daten, Bind Mounts für Entwicklung. Regelmäßige Backups nicht vergessen.