Block 1 – Grundkonzepte & Theorie
Dauer: ca. 40 Minuten
Ziel: Verstehen was Container sind, wie sie funktionieren und warum Podman auf RHEL die erste Wahl ist.
💡 Roter Faden: In diesem Kurs arbeiten wir durchgehend mit einem nginx-Container. Was wir hier starten, werden wir in jedem Block weiter ausbauen.
Einstieg – Eine bekannte Situation
Stell dir vor: Du bekommst einen Anruf.
"Der nginx läuft nicht mehr."
Du loggst dich ein. systemctl status nginx – kein Dienst. ps aux | grep nginx – kein Prozess. Nichts.
Dann bemerkst du:
Willkommen in der Welt der Container. Alles was du bisher über Dienste und Prozesse weisst, gilt noch – aber die Werkzeuge sind andere. Genau das schauen wir uns heute an.
1.1 Was ist ein Container?
Ein Container ist ein isolierter Prozess auf dem Host-System. Er teilt sich den Kernel mit dem Host, hat aber seine eigene Sicht auf Dateisystem, Netzwerk, Prozesse und Benutzer.
Container vs. Virtuelle Maschine
┌─────────────────────────────────────────────────────────────────┐
│ VIRTUELLE MASCHINE │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ App A + Libraries │ │ App B + Libraries │ │
│ ├──────────────────────┤ ├──────────────────────┤ │
│ │ Guest OS (Linux) │ │ Guest OS (Linux) │ │
│ └──────────┬───────────┘ └──────────┬───────────┘ │
│ │ Hypervisor │ │
│ └───────────────┬───────────┘ │
│ Host OS │
│ Hardware │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ CONTAINER (Podman) │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ App A + Libraries │ │ App B + Libraries │ │
│ └──────────┬───────────┘ └──────────┬───────────┘ │
│ │ Podman (daemonless) │ │
│ └───────────────┬───────────┘ │
│ Host OS (gemeinsamer Kernel) │
│ Hardware │
└─────────────────────────────────────────────────────────────────┘
| Virtuelle Maschine | Container | |
|---|---|---|
| Startzeit | 1–2 Minuten | Sekunden |
| Grösse | GBs (volles OS) | MBs (nur App + Libs) |
| Isolation | Eigener Kernel | Gemeinsamer Kernel |
| Overhead | Hoch | Minimal |
"Eine VM ist wie ein eigenes Haus mit eigenem Fundament. Ein Container ist wie eine Wohnung im gleichen Gebäude – eigene Türe, eigene Einrichtung, aber gemeinsame Tragstruktur."
Vorteile für den Sysadmin-Alltag
- Applikation läuft überall gleich – kein "bei mir funktioniert's"
- Kein Dependency-Chaos mehr auf dem Host
- Schnell starten, schnell wegwerfen, schnell ersetzen
- Mehrere Versionen der gleichen App parallel betreiben
1.2 Wie funktioniert das technisch?
Container bauen auf drei Linux-Kernelmechanismen auf:
| Mechanismus | Aufgabe | Analogie |
|---|---|---|
| Namespaces | Isolation: Container sieht nur seine eigenen Prozesse, sein Netzwerk, sein Dateisystem | Wie chroot, aber viel mächtiger |
| cgroups | Ressourcenlimitierung: CPU, RAM, I/O pro Container begrenzen | Wie ulimit, aber granularer |
| Union Filesystem | Layer-basiertes Dateisystem: Images aus übereinandergestapelten Schichten | Wie Git-Commits übereinandergelegt |
1.3 Images, Layer und der R/W-Layer
Das Layer-Modell
Ein Image ist aus mehreren read-only Schichten aufgebaut. Jede Schicht entspricht einem Schritt beim Bauen des Images:
┌───────────────────────────────────────┐
│ nginx config Layer │ ← COPY nginx.conf (read-only)
├───────────────────────────────────────┤
│ nginx binary Layer │ ← RUN dnf install nginx (read-only)
├───────────────────────────────────────┤
│ UBI Base Image │ ← FROM ubi9/ubi-minimal (read-only)
└───────────────────────────────────────┘
▲ Image – unveränderlich, shared zwischen allen Containern
Gemeinsame Schichten werden nur einmal auf der Disk gespeichert. Zehn nginx-Container teilen sich das gleiche Basis-Image.
Was passiert beim podman run?
Beim Start legt Podman eine dünne read/write Schicht oben drauf – temporär, nur für diesen Container:
┌───────────────────────────────────────┐ ← R/W Layer (temporär, nur dieser Container)
├───────────────────────────────────────┤ ← nginx config Layer (read-only, shared)
├───────────────────────────────────────┤ ← nginx binary Layer (read-only, shared)
└───────────────────────────────────────┘ ← UBI Base Image (read-only, shared)
Ein Image – beliebig oft gestartet
Das gleiche Image kann parallel in mehreren Containern laufen. Jede Instanz bekommt ihre eigene R/W-Schicht:
Image: nginx:latest (read-only, einmal auf Disk)
│
├──→ Container web1 [eigene R/W Schicht]
├──→ Container web2 [eigene R/W Schicht]
└──→ Container web3 [eigene R/W Schicht]
podman run -d --name web1 nginx
podman run -d --name web2 nginx
podman run -d --name web3 nginx
# Alle drei laufen – gleiches Image, unabhängige Container
"Das Image ist wie ein VM-Template. Jedes Mal wenn du einen Container startest, bekommst du eine frische Kopie – beliebig oft, sofort."
Änderungen sind flüchtig
Alles was du im Container änderst, liegt in der R/W-Schicht. Löscht du den Container, ist die R/W-Schicht weg:
podman exec -it mein-nginx bash
echo "test" > /tmp/meinedatei.txt
exit
podman rm mein-nginx
# → /tmp/meinedatei.txt ist weg. Das Image ist unberührt.
Persistenz nur über Mounts oder Volumes:
Bind Mount → Ordner vom Host direkt in den Container eingebunden
Volume → Von Podman verwalteter Speicher, überlebt den Container
"Was du im Container änderst ist beim nächsten Start weg – ausser du hast einen Mount. Das ist gewollt: jeder Start ist eine saubere, reproduzierbare Umgebung."
→ Mehr dazu in Block 3.
1.4 Docker vs. Podman
Auf RHEL ist Podman der Standard – kein Docker:
| Docker | Podman | |
|---|---|---|
| Daemon | Zentraler dockerd läuft als root |
Kein Daemon – daemonless |
| Root | Daemon läuft immer als root | Rootless möglich |
| RHEL-Support | Nicht offiziell supportet | Red Hat Produkt, vollständig supportet |
| Befehle | docker run, docker ps |
podman run, podman ps |
| Kompatibilität | — | Syntax nahezu identisch |
| Pods | Nur via Kubernetes | Nativ unterstützt |
Wichtig: Wer Docker kennt, kennt 95% von Podman.
docker run nginxwird einfach zupodman run nginx.
Warum kein Daemon ein Vorteil ist
Docker: Podman:
┌─────────────────────┐ ┌─────────────────────┐
│ dockerd (root) │ │ kein Daemon │
│ ┌───────────────┐ │ │ │
│ │ Container 1 │ │ │ Container 1 ──────→ Kernel
│ │ Container 2 │ │ │ Container 2 ──────→ Kernel
│ │ Container 3 │ │ │ Container 3 ──────→ Kernel
│ └───────────────┘ │ │ │
└─────────────────────┘ └─────────────────────┘
Daemon kompromittiert Kein Single Point
= root auf dem System of Failure
"Der Docker-Daemon ist wie ein Hausmeister mit Generalschlüssel der immer im Gebäude ist. Podman hat keinen Hausmeister – jeder Bewohner öffnet seine eigene Türe."
⚠️ Sicherheitswarnung: sudo podman / sudo docker
Wer sudo podman oder sudo docker ausführen darf – oder Zugriff auf den Docker-Socket hat – hat effektiv root-Rechte auf dem ganzen Host:
# Triviales Beispiel: Host-Filesystem als root lesen
sudo podman run --rm -v /:/host alpine cat /host/etc/shadow
# Noch gefährlicher: Shell als root auf dem Host
sudo podman run --rm -it -v /:/host alpine chroot /host
# → Du bist root auf dem Host!
"sudo podman ist wie sudo bash – wer Container mit root-Rechten starten darf, kann auf alles auf dem Host zugreifen. Rootless Podman ohne sudo ist deshalb kein Komfort-Feature, sondern eine Sicherheitsmassnahme."
Das ist der Grund warum wir in diesem Kurs konsequent rootless arbeiten – ohne sudo.
Podman Pods
Podman kennt das Konzept der Pods – direkt von Kubernetes inspiriert:
- Ein Pod gruppiert mehrere Container die sich Netzwerk und Storage teilen
- Alle Container in einem Pod kommunizieren über localhost
- Im Alltag selten direkt nötig – aber der Begriff begegnet dir bei Kubernetes wieder
1.5 Images und Registry
Was ist eine Registry?
Eine Registry ist ein Speicher für Images:
┌──────────┐ push ┌──────────────┐ pull ┌──────────────┐
│Entwickler│ ───────→ │ Registry │ ───────→ │ Server │
│baut Image│ │ (Artifactory│ │startet Contai│
└──────────┘ │ docker.io │ └──────────────┘
│ quay.io) │
└──────────────┘
Bekannte Registries:
| Registry | URL | Nutzung |
|---|---|---|
| Red Hat Registry | registry.redhat.io |
Offizielle RHEL/UBI-Images |
| Quay.io | quay.io |
Red Hat Community Registry |
| Docker Hub | docker.io |
Allgemeine öffentliche Images |
| Firmen-Registry | Artifactory intern | Eigene/interne Images |
Image-Namen verstehen
registry.redhat.io / ubi9/nginx : 1.24
│ │ │
│ │ └─ Tag (Version)
│ └─ Image-Name
└─ Registry-Adresse
Empfehlung: Immer vollständige Image-Namen verwenden – nie nur
nginx, immerdocker.io/library/nginx:latest.
1.6 OCI-Standard & verwandte Tools
OCI = Open Container Initiative – offener Standard für Images und Container-Laufzeit. Ein Docker-Image läuft auch mit Podman, und umgekehrt.
| Tool | Zweck |
|---|---|
podman |
Container starten, verwalten, inspizieren |
buildah |
Images bauen – intern von Podman verwendet |
podman compose |
Compose-Dateien ausführen (integriert seit Podman 4.7) |
Übung 1 – Erste Schritte mit nginx
🔴 Roter Faden: Diesen nginx-Container begleiten wir durch den ganzen Kurs.
💡 Variablen setzen – einmalig pro Session, dann in Block 2 erklärt:
Aufgabe 1a – Image pullen und inspizieren
podman pull docker.io/library/nginx:latest
podman images
podman history docker.io/library/nginx:latest
Fragen: 1. Wie viele Layer hat das nginx-Image? 2. Wie gross ist das Image?
Aufgabe 1b – Container starten
# nginx starten – Port aus deiner ~/.kurs-info
podman run -d --name mein-nginx -p ${PORT}:80 docker.io/library/nginx:latest
podman ps
curl http://localhost:${PORT}
Aufgabe 1c – Flüchtigkeit live erleben
# Datei im Container erstellen
podman exec -it mein-nginx bash
echo "ich bin temporaer" > /tmp/test.txt
exit
# Container löschen und neu starten
podman stop mein-nginx && podman rm mein-nginx
podman run -d --name mein-nginx -p ${PORT}:80 docker.io/library/nginx:latest
# Datei noch da?
podman exec -it mein-nginx bash
cat /tmp/test.txt
exit
Datei noch da?
podman exec -it mein-nginx bash cat /tmp/test.txt exit
---
## Musterlösung Übung 1
### 1a
```bash
podman images
# REPOSITORY TAG IMAGE ID SIZE
# docker.io/library/nginx latest a1b2c3d4e5f6 187 MB
podman history docker.io/library/nginx:latest
# → 7–10 Layer typischerweise
1b
podman ps
# CONTAINER ID IMAGE STATUS PORTS
# a1b2c3d4 nginx Up 5 seconds 0.0.0.0:${PORT}->80/tcp
curl http://localhost:8100
# <!DOCTYPE html>... ← nginx Welcome Page
1c
Erklärung: Die Datei lag in der R/W-Schicht des Containers. Mit podman rm wurde diese Schicht gelöscht. Der neue Container hat eine frische, leere R/W-Schicht – das Image selbst ist unberührt.
Konsequenz für den Alltag: Logs, Daten, Konfigurationsänderungen die nur im Container gemacht werden, sind beim nächsten Start weg → immer Mounts oder Volumes verwenden für alles was persistiert werden soll.
Weiterführende Links
| Thema | Link |
|---|---|
| Podman offizielle Dokumentation | docs.podman.io |
| Red Hat – Container Guide (RHEL 9) | access.redhat.com – Building, Running and Managing Containers |
| Red Hat – Was ist Podman? | redhat.com – What is Podman |
| Red Hat UBI – Universal Base Images | catalog.redhat.com/software/base-images |
| OCI – Open Container Initiative | opencontainers.org |