Block 3 – Storage: Volumes & Mounts
Dauer: ca. 30 Minuten
Ziel: Verstehen wie Daten persistent gemacht werden – und das Aha-Erlebnis live erleben.
💡 Roter Faden: Wir geben unserem nginx eine eigene Webseite – mit einer Datei vom Host.
3.1 Das Problem: Daten sind flüchtig
Aus Block 1 wissen wir: Alles was im Container verändert wird, liegt in der R/W-Schicht und ist beim nächsten Start weg.
Für den Sysadmin-Alltag bedeutet das: - Logfiles im Container → beim Neustart weg - Konfigurationsänderungen direkt im Container → beim Neustart weg - Datenbank-Daten ohne Volume → beim Neustart weg
Die Lösung: Storage von aussen einbinden.
3.2 Drei Arten von Storage
┌─────────────────────────────────────────────────────────────┐
│ HOST │
│ │
│ /home/user/webroot/ podman volume tmpfs (RAM) │
│ │ │ │ │
│ │ Bind Mount │ Volume │ tmpfs Mount │
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ CONTAINER │ │
│ │ /usr/share/nginx/html /data /tmp/cache │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
| Typ | Beschreibung | Analogie | Wann verwenden |
|---|---|---|---|
| Bind Mount | Host-Pfad direkt in Container | Symlink auf einen Ordner | Configs, Entwicklung, direkter Zugriff nötig |
| Volume | Von Podman verwalteter Speicher | NFS-Mount – der Container geht, die Daten bleiben | Datenbanken, persistente App-Daten |
| tmpfs | Nur im RAM, flüchtig | Ramdisk | Temporäre Dateien, Secrets, Performance |
3.3 Bind Mount – Das Aha-Erlebnis
Ein Bind Mount verbindet einen Host-Pfad direkt mit einem Container-Pfad.
"Ein Bind Mount ist wie ein Symlink auf einen Ordner – du siehst direkt was auf dem Host liegt. Änderung auf dem Host = sofort im Container sichtbar."
# Syntax
podman run -v /host/pfad:/container/pfad image
# Beispiel: eigenen Webroot einbinden
podman run -d \
--name mein-nginx \
-p ${PORT}:80 \
-v /home/teilnehmer01/webroot:/usr/share/nginx/html:ro \
nginx
Mount-Optionen
-v /host/pfad:/container/pfad:ro → read-only (Container kann nicht schreiben)
-v /host/pfad:/container/pfad:rw → read-write (Standard)
-v /host/pfad:/container/pfad:z → SELinux-Label setzen (shared)
-v /host/pfad:/container/pfad:Z → SELinux-Label setzen (private)
💡 SELinux-Hinweis (RHEL): Auf RHEL mit aktivem SELinux kann es beim Bind Mount zu "Permission denied" kommen, obwohl die Linux-Berechtigungen stimmen. In diesem Fall
:zoder:Zanhängen.:zfür geteilten Zugriff,:Zfür exklusiven Zugriff durch diesen Container.
3.4 Volumes – Persistente Daten
Ein Volume wird von Podman verwaltet und überlebt den Container.
"Ein Volume ist wie ein NFS-Mount – der Container geht, die Daten bleiben. Podman kümmert sich darum wo die Daten liegen."
# Volume erstellen
podman volume create meine-daten
# Volume anzeigen
podman volume ls
# Volume inspizieren (wo liegt es wirklich?)
podman volume inspect meine-daten
# → Mountpoint: /home/user/.local/share/containers/storage/volumes/meine-daten/_data
# Container mit Volume starten
podman run -d \
--name mein-nginx \
-v meine-daten:/usr/share/nginx/html \
nginx
# Volume entfernen (nur wenn nicht verwendet)
podman volume rm meine-daten
# Alle unbenutzten Volumes entfernen
podman volume prune
Bind Mount vs. Volume – wann was?
| Bind Mount | Volume | |
|---|---|---|
| Pfad bekannt? | Ja – du gibst ihn an | Nein – Podman verwaltet |
| Direkter Host-Zugriff? | Ja | Nur via podman volume inspect |
| Portabilität | Pfad muss auf jedem Host gleich sein | Überall gleich |
| Typischer Einsatz | Configs, Webroot, Logs | Datenbank-Daten, App-State |
3.5 Dateiberechtigungen und UID/GID
Das ist eine häufige Fehlerquelle im Alltag. Container-Prozesse laufen mit einer bestimmten UID – und die muss zu den Berechtigungen der gemounteten Dateien passen.
# Welche UID läuft im Container?
podman exec mein-nginx id
# uid=101(nginx) gid=101(nginx)
# Welche Berechtigungen hat der Host-Ordner?
ls -la /home/teilnehmer01/webroot/
# drwxr-x--- 2 teilnehmer01 teilnehmer01 4096
# → nginx (UID 101) kann nicht lesen!
"Ein UID-Mismatch im Container ist wie ein falsch gesetzter
chownnach einem Restore – der Prozess startet, aber kommt nicht an seine eigenen Dateien ran."
Lösung
# Option 1: Berechtigungen anpassen
chmod o+rx /home/teilnehmer01/webroot/
chmod o+r /home/teilnehmer01/webroot/*
# Option 2: Besitzer anpassen (auf die UID im Container)
chown -R 101:101 /home/teilnehmer01/webroot/
# Option 3: Bei rootless Podman – UID-Mapping verstehen
# Der Container-Prozess läuft als UID 101 innerhalb des Containers
# Auf dem Host wird diese UID gemappt auf eine sub-UID des Users
# Mehr dazu in Block 7
Welche UID sieht der Host?
# Im Container
podman exec mein-nginx id
# uid=0(root)
# Auf dem Host – was sieht der Host wirklich?
ps aux | grep nginx
# teilnehm+ 1234 nginx: master process
# → Als User-Prozess des Teilnehmers, nicht als root!
# Das ist Rootless Podman in Aktion – mehr in Block 7
3.6 Mounts inspizieren
# Welche Mounts hat ein Container?
podman inspect --format '{{.Mounts}}' mein-nginx
# Besser lesbar
podman inspect mein-nginx | grep -A20 '"Mounts"'
# Oder direkt im laufenden Container
podman exec mein-nginx df -h
podman exec mein-nginx mount | grep -v "proc\|sys\|dev"
Übung 3 – Eigene Webseite in nginx
🔴 Roter Faden: Wir geben unserem nginx eine eigene Startseite – direkt vom Host gemountet.
💡 Variablen setzen falls noch nicht geschehen (aus Block 2):
Aufgabe 3a – Das Aha-Erlebnis: Bind Mount
# 1. Eigenen Webroot erstellen
mkdir -p ~/webroot
# 2. Eigene index.html erstellen
cat > ~/webroot/index.html << EOF
<html>
<head><title>Mein Container</title></head>
<body>
<h1>Hallo vom Host</h1>
<p>Diese Datei liegt auf dem Host unter ~/webroot/</p>
<p>User: ${USER_NAME}</p>
</body>
</html>
EOF
# 3. Alten Container entfernen
podman stop mein-nginx && podman rm mein-nginx
# 4. Neuen Container mit Bind Mount starten
podman run -d \
--name mein-nginx \
-p ${PORT}:80 \
-v ~/webroot:/usr/share/nginx/html:ro \
docker.io/library/nginx:latest
# 5. Testen
curl http://localhost:${PORT}
⚠️ Permission denied? Das ist normal und erwartet. nginx läuft im Container als UID 101 (
Mehr zu UID/GID-Problemen in Abschnitt 3.5.nginx-User), aber~/webroot/gehört deinem User. Lösung:
Fragen: 1. Siehst du deine eigene HTML-Seite? 2. Was passiert wenn du die Datei auf dem Host änderst?
# Datei auf dem Host ändern
echo "<h1>Ich wurde geaendert</h1>" > ~/webroot/index.html
# Sofort im Container sichtbar?
curl http://localhost:${PORT}
Aufgabe 3b – Volume erstellen und verwenden
# Volume erstellen
podman volume create nginx-logs
# nginx mit Log-Volume starten
podman stop mein-nginx && podman rm mein-nginx
podman run -d \
--name mein-nginx \
-p ${PORT}:80 \
-v ~/webroot:/usr/share/nginx/html:ro \
-v nginx-logs:/var/log/nginx \
docker.io/library/nginx:latest
# Logs generieren
curl http://localhost:${PORT}
curl http://localhost:${PORT}/nichtvorhanden
# Volume inspizieren
podman volume inspect nginx-logs
# Logs direkt auf dem Host lesen (Pfad aus inspect)
ls -la ~/.local/share/containers/storage/volumes/nginx-logs/_data/
Aufgabe 3c – Was passiert beim Container löschen?
# Container löschen
podman rm -f mein-nginx
# Volume noch vorhanden?
podman volume ls
# → nginx-logs ist noch da!
# Neuen Container mit gleichem Volume starten
podman run -d \
--name mein-nginx \
-p ${PORT}:80 \
-v ~/webroot:/usr/share/nginx/html:ro \
-v nginx-logs:/var/log/nginx \
docker.io/library/nginx:latest
# Alte Logs noch vorhanden?
podman exec mein-nginx cat /var/log/nginx/access.log
Musterlösung Übung 3
3a
curl http://localhost:${PORT}
# <html><head><title>Mein Container</title></head>...
# → Eigene Seite wird angezeigt!
echo "<h1>Ich wurde geaendert</h1>" > ~/webroot/index.html
curl http://localhost:${PORT}
# <h1>Ich wurde geändert!</h1>
# → Sofort sichtbar – kein Container-Neustart nötig!
Das ist das Aha-Erlebnis: Die Datei liegt auf dem Host – der Container sieht sie direkt. Keine Kopie, kein Sync, keine Verzögerung.
3b
podman volume inspect nginx-logs
# [
# {
# "Name": "nginx-logs",
# "Mountpoint": "/home/teilnehmer01/.local/share/containers/storage/volumes/nginx-logs/_data",
# ...
# }
# ]
ls ~/.local/share/containers/storage/volumes/nginx-logs/_data/
# access.log error.log
3c
podman volume ls
# DRIVER VOLUME NAME
# local nginx-logs
# → Volume überlebt den Container
podman exec mein-nginx cat /var/log/nginx/access.log
# → Alte Log-Einträge noch vorhanden!
Weiterführende Links
| Thema | Link |
|---|---|
| Podman Volumes | docs.podman.io – podman-volume |
| Red Hat – Storage in Containern | access.redhat.com – Using storage |
| SELinux und Container | access.redhat.com – SELinux Container security |