# Einfuehrung in Podman

Dieser Text ist eine allgemeine Grundlagen-Einfuehrung in Podman, unabhaengig
vom konkreten Projekt. Wer bereits Docker kennt, findet fast alles wieder;
wer noch nie mit Containern gearbeitet hat, findet hier den Einstieg von Null.
Fuer den projektspezifischen Teil (Novaris, OpenShift, `shared/enterprise-infrastructure`) siehe
[Exkurs: Podman im Novaris-Projekt](18-podman-exkurs.md).

## 1. Was ist ein Container?

Ein Container ist ein isolierter Prozess, der ein eigenes Dateisystem, eigene
Umgebungsvariablen und eigene Netzwerksicht mitbringt, sich dabei aber den
Kernel des Host-Betriebssystems mit anderen Containern teilt. Im Unterschied
zu einer virtuellen Maschine muss also kein eigenes Betriebssystem gebootet
werden - ein Container startet in Sekunden statt Minuten.

Zwei Begriffe stehen dabei im Zentrum:

- **Image**: eine unveraenderliche, schreibgeschuetzte Vorlage (vergleichbar
  mit einer Installationsdatei plus vorkonfiguriertem Zustand).
- **Container**: eine laufende oder gestoppte Instanz eines Images, mit einer
  eigenen beschreibbaren Schicht obendrauf.

Aus einem Image lassen sich beliebig viele, voneinander unabhaengige
Container starten.

## 2. Warum Podman und nicht Docker?

Podman verfolgt dieselbe grundlegende Idee wie Docker und ist zur
Docker-Kommandozeile weitgehend kompatibel - die meisten `docker`-Befehle
funktionieren nahezu unveraendert mit `podman` statt `docker`. Der wichtigste
architektonische Unterschied:

- **Docker** braucht einen dauerhaft laufenden, meist mit Root-Rechten
  gestarteten Hintergrunddienst (den Docker-Daemon), der alle Container
  verwaltet.
- **Podman** kommt ohne einen solchen zentralen Daemon aus. Jeder
  `podman`-Befehl startet einen eigenstaendigen Prozess. Container koennen
  dadurch auch ohne Root-Rechte laufen ("rootless"), was aus
  Sicherheitssicht ein Vorteil ist.

Fuer die taegliche Arbeit an der Kommandozeile macht das kaum einen
Unterschied - der Umstieg besteht meist nur darin, `docker` durch `podman`
zu ersetzen.

## 3. Installation und erster Test

Nach der Installation (siehe offizielle Podman-Dokumentation fuer das
jeweilige Betriebssystem) mit folgendem Befehl pruefen, ob alles funktioniert:

```powershell
podman version
podman info
```

Unter Windows und macOS laeuft Podman nicht direkt auf dem Host, sondern in
einer schlanken Linux-VM, die Podman selbst verwaltet ("Podman Machine").
Details dazu, inklusive der projektspezifischen Stolpersteine unter Windows,
stehen im [Podman-Exkurs](18-podman-exkurs.md#1-architektur-unter-windows).

## 4. Der erste Container

Ein bekanntes Testimage herunterladen und starten:

```powershell
podman run hello-world
```

Ein laenger laufender Dienst, im Hintergrund gestartet und mit
Port-Weiterleitung:

```powershell
podman run -d --name web -p 8080:80 nginx:latest
```

Danach ist der Dienst unter `http://localhost:8080` erreichbar. Die
wichtigsten Optionen dabei:

| Option | Bedeutung |
|---|---|
| `-d` | im Hintergrund ausfuehren ("detached") |
| `--name web` | Container einen Namen geben, statt einen zufaelligen zu erhalten |
| `-p 8080:80` | Host-Port 8080 auf Container-Port 80 weiterleiten |

## 5. Container verwalten

```powershell
podman ps            # laufende Container anzeigen
podman ps -a          # auch gestoppte Container anzeigen
podman logs web       # Ausgaben des Containers ansehen
podman exec -it web sh  # Shell im laufenden Container oeffnen
podman stop web       # Container anhalten
podman start web      # gestoppten Container wieder starten
podman rm web         # Container endgueltig entfernen
```

Wichtig: `podman rm` entfernt nur den Container, nicht das zugrunde liegende
Image. Ein neuer Container aus demselben Image laesst sich danach jederzeit
wieder starten.

## 6. Mit Images arbeiten

```powershell
podman images          # lokal vorhandene Images auflisten
podman pull postgres:16  # Image aus einer Registry herunterladen
podman rmi postgres:16   # Image lokal entfernen
```

Ein Image besteht aus einem Namen und einem Tag, getrennt durch einen
Doppelpunkt, zum Beispiel `postgres:16`. Fehlt der Tag, wird `latest`
angenommen - fuer reproduzierbare Umgebungen ist ein fester Tag jedoch
vorzuziehen, da sich `latest` unbemerkt aendern kann.

## 7. Eigene Images bauen

Ein `Containerfile` (bei Docker meist `Dockerfile` genannt, von Podman
gleichwertig unterstuetzt) beschreibt, wie ein Image aufgebaut wird:

```dockerfile
FROM eclipse-temurin:21-jre
COPY target/app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
```

Daraus ein Image bauen und einen Container starten:

```powershell
podman build -t meine-app:local .
podman run -d --name meine-app -p 8080:8080 meine-app:local
```

## 8. Daten dauerhaft speichern: Volumes

Das beschreibbare Dateisystem eines Containers verschwindet mit
`podman rm`. Fuer Daten, die einen Container ueberdauern sollen (zum Beispiel
eine Datenbank), dienen Volumes:

```powershell
podman volume create db-data
podman run -d --name db `
  -e POSTGRES_PASSWORD=test `
  -v db-data:/var/lib/postgresql/data `
  postgres:16
```

Auch nach `podman rm db` bleiben die Daten im Volume `db-data` erhalten und
koennen von einem neuen Container wiederverwendet werden.

## 9. Mehrere Container verbinden: Netzwerke

Container in einem gemeinsamen Podman-Netzwerk erreichen sich gegenseitig
ueber ihren Containernamen als Hostnamen:

```powershell
podman network create mein-netz
podman run -d --name db --network mein-netz postgres:16
podman run -d --name app --network mein-netz meine-app:local
```

Die Anwendung im Container `app` kann die Datenbank also unter dem Hostnamen
`db` erreichen (nicht `localhost`).

## 10. Aufraeumen

```powershell
podman ps -a               # Bestandsaufnahme: was existiert ueberhaupt?
podman container prune     # gestoppte Container entfernen
podman image prune         # ungenutzte Images entfernen
podman volume prune        # ungenutzte Volumes entfernen (loescht Daten!)
podman system df -v        # Speicherverbrauch aller Ressourcen anzeigen
```

Vor `podman volume prune` immer pruefen, ob sich in einem Volume noch
benoetigte Daten befinden - das Entfernen ist nicht rueckgaengig zu machen.

## 11. Docker-Befehle uebersetzen

Wer Docker bereits kennt, kann fast jeden Befehl direkt uebertragen:

| Docker | Podman |
|---|---|
| `docker run ...` | `podman run ...` |
| `docker ps` | `podman ps` |
| `docker build ...` | `podman build ...` |
| `docker images` | `podman images` |
| `docker exec ...` | `podman exec ...` |
| `docker-compose up` | `podman compose up` |

## Merksatz

Ein Image ist eine Vorlage, ein Container eine laufende Instanz davon.
Podman verwaltet beides ohne zentralen Hintergrund-Daemon und ermoeglicht
dadurch rootless Container. Fuer dauerhafte Daten sorgen Volumes, fuer die
Kommunikation zwischen Containern sorgen Netzwerke - beides ueberlebt das
Entfernen eines einzelnen Containers.
