Block 2 – Grundbefehle & täglicher Betrieb
Dauer: ca. 50 Minuten
Ziel: Überblick verschaffen, Container analysieren, sicher navigieren – die wichtigsten Werkzeuge für den Alltag.
💡 Roter Faden: Wir arbeiten weiter mit dem nginx-Container aus Block 1.
Kursvariablen setzen
Bevor wir starten – setze diese zwei Variablen in deiner Session. Alle Befehle in diesem Kurs verwenden sie, damit du nichts manuell ersetzen musst:
# Deinen Username (wird automatisch gesetzt)
export USER_NAME=$(whoami)
# Deinen Port (steht in deiner ~/.kurs-info)
export PORT=8100 # teilnehmer01
# export PORT=8200 # teilnehmer02
# export PORT=8300 # teilnehmer03
# Prüfen
echo "User: ${USER_NAME} | Port: ${PORT}"
⚠️ Wichtig: Diese Variablen gelten nur für die aktuelle SSH-Session. Nach einem neuen Login müssen sie neu gesetzt werden. Tipp: in
~/.bashrceintragen damit sie automatisch gesetzt werden:
2.1 Unbekannter Server – was läuft hier überhaupt?
Bevor du podman ps tippst: Auf einem unbekannten Server musst du zuerst klären was für Container-Technologie überhaupt installiert und aktiv ist. Die Möglichkeiten sind vielfältiger als man denkt:
Mögliche Container-Technologien auf einem Server:
├── Podman (rootful oder rootless)
├── Docker (mit dockerd-Daemon)
├── Kubernetes (kubectl + kubelet)
├── k3s (leichtgewichtiges Kubernetes)
└── Kombinationen davon
# Schritt 1 – Was ist installiert?
which docker podman kubectl k3s 2>/dev/null
# Schritt 2 – Welche Dienste laufen?
systemctl is-active docker # Docker aktiv?
systemctl is-active podman.socket # Podman Socket aktiv?
systemctl is-active kubelet # Kubernetes Node-Agent?
systemctl is-active k3s # k3s aktiv?
# Schritt 3 – Kubernetes/k3s läuft?
kubectl get nodes 2>/dev/null # Kubernetes Cluster erreichbar?
k3s kubectl get pods 2>/dev/null # k3s Pods
# Schritt 4 – Rootful Container (root-Ebene)
sudo docker ps 2>/dev/null # Docker Container
sudo podman ps 2>/dev/null # Podman root Container
# Schritt 5 – Rootless Container irgendwo?
ps aux | grep conmon # conmon = läuft hinter jedem Podman-Container
ps aux | grep containerd # containerd = Laufzeit für Docker und k8s
ps aux | grep kubelet # Kubernetes Node-Agent
# Schritt 6 – Welche User haben Container?
ls /home/ # Welche User gibt es?
sudo -u teilnehmer01 podman ps # Container eines bestimmten Users
"Auf einem unbekannten Server immer zuerst klären womit du es zu tun hast.
ps aux | grep -E 'conmon|containerd|kubelet'gibt dir in einer Zeile einen Überblick ob und was für Container-Technologie aktiv ist."
Die Technologien und ihre Werkzeuge
| Technologie | Erkennung | Befehle |
|---|---|---|
| Podman | which podman |
podman ps, podman ps -a |
| Docker | systemctl is-active docker |
docker ps, docker ps -a |
| Kubernetes | systemctl is-active kubelet |
kubectl get pods -A |
| k3s | systemctl is-active k3s |
k3s kubectl get pods -A |
"Bei Kubernetes und k3s fragst du nicht nach Containern – du fragst nach Pods. Die Container darin werden von Kubernetes verwaltet, nicht direkt von dir."
Wichtig: podman ps zeigt nur deine Container
teilnehmer01: podman ps → nur Container von teilnehmer01
teilnehmer02: podman ps → nur Container von teilnehmer02
root: podman ps → nur root-Container (NICHT die rootless User!)
Root sieht also auch nicht alle Container automatisch. Rootless Container laufen im User-Namespace – selbst root bekommt keinen automatischen Überblick.
# Schnellster Überblick über ALLE laufenden Container-Prozesse
ps aux | grep -E 'conmon|containerd|kubelet'
# → Zeigt alle Container-Technologien die aktiv sind
2.2 Überblick verschaffen – "Was läuft hier?"
Wenn du weisst womit du es zu tun hast, ist das dein erster Griff:
# Nur laufende Container
podman ps
# Alle Container – auch gestoppte
podman ps -a
# Kompaktere Ausgabe mit mehr Details
podman ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}\t{{.Image}}"
"
podman psist deinps auxfür Container – der erste Blick auf das System."
Was sagt mir die Ausgabe?
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 docker.io/library/nginx:latest 2 hours ago Up 2 hours 0.0.0.0:8100->80/tcp mein-nginx
b2c3d4e5f6a1 docker.io/library/nginx:latest 1 hour ago Exited (1) 5 min crashed-nginx
| Feld | Bedeutung |
|---|---|
STATUS |
Up = läuft, Exited (0) = sauber beendet, Exited (1) = Fehler |
PORTS |
0.0.0.0:8100->80/tcp = Host-Port 8100 → Container-Port 80 |
NAMES |
Vergibst du mit --name, sonst zufällig generiert |
2.3 Details zu einem Container
# Vollständige Informationen (JSON)
podman inspect mein-nginx
# Gezielt einzelne Felder herausfiltern
podman inspect --format '{{.State.Status}}' mein-nginx # Status
podman inspect --format '{{.NetworkSettings.IPAddress}}' mein-nginx # IP
podman inspect --format '{{.Mounts}}' mein-nginx # Mounts
podman inspect --format '{{.Config.Env}}' mein-nginx # Umgebungsvariablen
# Ports anzeigen
podman port mein-nginx
"
podman inspectist wiecat /proc/<pid>/status– alles was du über den Container wissen willst, auf einen Blick. Nur etwas gesprächiger."
Ressourcenverbrauch live
# Live-Statistiken (wie top, aber für Container)
podman stats
# Nur bestimmte Container
podman stats mein-nginx
# Einmalige Ausgabe ohne Live-Update
podman stats --no-stream
Prozesse im Container sehen
# Was läuft im Container?
podman top mein-nginx
# Mit Feldern wie ps aux
podman top mein-nginx pid,user,comm,args
2.4 Logs lesen
# Alle Logs
podman logs mein-nginx
# Letzte 20 Zeilen
podman logs --tail 20 mein-nginx
# Live mitlesen (wie tail -f)
podman logs -f mein-nginx
# Mit Zeitstempel
podman logs -t mein-nginx
# Seit einem bestimmten Zeitpunkt
podman logs --since 30m mein-nginx
podman logs --since "2024-01-15T10:00:00" mein-nginx
"
podman logsist deinjournalctlfür Container. Ohne Logs kein Troubleshooting."
2.5 In einen Container einsteigen – podman exec
podman exec ist eines der wichtigsten Werkzeuge im Alltag. Es führt einen Befehl in einem laufenden Container aus – ohne den Container neu zu starten.
"
podman execist wie SSH in eine VM – nur ohne Netzwerk, ohne SSH-Daemon, direkt in den Prozess-Namespace."
# Interaktive Shell im Container
podman exec -it mein-nginx bash
# Oder sh wenn bash nicht vorhanden
podman exec -it mein-nginx sh
# Einzelnen Befehl ausführen ohne Shell
podman exec mein-nginx cat /etc/nginx/nginx.conf
podman exec mein-nginx nginx -t # nginx Config testen
podman exec mein-nginx id # Welcher User läuft?
podman exec mein-nginx env # Umgebungsvariablen
podman exec mein-nginx ps aux # Prozesse im Container
Typische Anwendungsfälle
| Situation | Befehl |
|---|---|
| nginx-Config prüfen | podman exec mein-nginx nginx -t |
| Welcher User läuft im Container? | podman exec mein-nginx id |
| Netzwerk-Verbindung testen | podman exec mein-nginx curl http://andere-app |
| Log-Datei direkt lesen | podman exec mein-nginx cat /var/log/nginx/error.log |
| Paket nachinstallieren (temporär!) | podman exec mein-nginx dnf install -y curl |
⚠️ Wichtig: Alles was du via exec änderst, liegt in der R/W-Schicht und ist beim nächsten Start weg. Für temporäre Analysen ideal – für dauerhafte Änderungen nicht geeignet.
exec vs. attach
# exec → neuer Prozess im Container (empfohlen)
podman exec -it mein-nginx bash
# attach → an den Hauptprozess anhängen (Vorsicht!)
podman attach mein-nginx
# → CTRL+C beendet hier den Hauptprozess = Container stoppt!
"Verwende immer
exec, nieattach. Mitattachhängst du dich direkt an den Hauptprozess – ein versehentliches CTRL+C und der Container ist weg."
2.6 Was hat sich verändert? – podman diff
# Zeigt alle Dateisystem-Änderungen seit Container-Start
podman diff mein-nginx
# A = Added, C = Changed, D = Deleted
# A /tmp/testfile
# C /var/log/nginx/access.log
"
podman diffist wiegit statusfür deinen Container – du siehst genau was sich in der R/W-Schicht verändert hat, ohne reinzugehen."
2.7 Container-Lifecycle
# Starten / Stoppen / Neustarten
podman start mein-nginx
podman stop mein-nginx # Graceful (SIGTERM, wartet 10s)
podman stop -t 30 mein-nginx # 30 Sekunden warten
podman restart mein-nginx
# Sofort beenden (SIGKILL – nur wenn stop nicht funktioniert)
podman kill mein-nginx
# Container entfernen
podman rm mein-nginx # Nur wenn gestoppt
podman rm -f mein-nginx # Erzwingen (auch laufend)
# Beim Start automatisch entfernen (ideal für Tests)
podman run --rm nginx echo "hallo" # Container weg nach Beendigung
⚠️ Produktions-Warnung:
"Niemals
podman rm -fauf einem unbekannten Container in Produktion – ohne vorher zu wissen was drin läuft und ob Daten verloren gehen."
2.8 Image-Management
# Lokale Images anzeigen
podman images
podman images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Image pullen
podman pull docker.io/library/nginx:latest
podman pull docker.io/library/nginx:1.24 # Spezifische Version
# Image entfernen
podman rmi docker.io/library/nginx:latest
# Alle nicht verwendeten Images löschen
podman image prune
# Layer-Aufbau anzeigen
podman history docker.io/library/nginx:latest
# Detailinfo zum Image
podman inspect docker.io/library/nginx:latest
2.9 Storage-Verzeichnisse – was wo liegt
Das ist wichtig für Disk-Management, Backup-Planung und Monitoring. Container-Technologien füllen Verzeichnisse die man kennen muss.
Podman – alle Varianten
┌─────────────────────────────────────────────────────────────────────┐
│ PODMAN STORAGE-ÜBERSICHT │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ROOTFUL (sudo podman) │
│ /var/lib/containers/storage/ ← Images, Container, Volumes │
│ /var/lib/containers/storage/volumes/ ← Named Volumes │
│ /run/containers/ ← Laufzeit-Daten (tmpfs) │
│ │
│ ROOTLESS (podman als User) │
│ ~/.local/share/containers/storage/ ← Images, Container │
│ ~/.local/share/containers/storage/volumes/ ← Named Volumes │
│ /run/user/<UID>/containers/ ← Laufzeit-Daten │
│ │
│ PRO USER – jeder User hat seinen eigenen Store! │
│ /home/user1/.local/share/containers/storage/ │
│ /home/user2/.local/share/containers/storage/ │
│ /home/user3/.local/share/containers/storage/ │
└─────────────────────────────────────────────────────────────────────┘
Docker – Verzeichnisse
┌─────────────────────────────────────────────────────────────────────┐
│ DOCKER STORAGE-ÜBERSICHT │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ROOTFUL (immer – Docker kennt kein rootless) │
│ /var/lib/docker/ ← Alles: Images, Container │
│ /var/lib/docker/volumes/ ← Named Volumes │
│ /var/lib/docker/overlay2/ ← Image-Layer (grösster Teil) │
│ /var/run/docker.sock ← Docker-Socket │
│ │
│ Docker hat KEINEN User-Store – alles liegt zentral unter root. │
└─────────────────────────────────────────────────────────────────────┘
Was wirklich Platz braucht
# Podman rootful – Übersicht
sudo du -sh /var/lib/containers/storage/
sudo podman system df
# Podman rootless – eigener Store
du -sh ~/.local/share/containers/storage/
podman system df
# Podman rootless – alle User auf dem System (als root)
du -sh /home/*/.local/share/containers/storage/ 2>/dev/null
# Docker
sudo du -sh /var/lib/docker/
sudo docker system df
"Wenn die Disk voll ist, ist
/var/lib/containersoder/var/lib/dockersehr oft der Schuldige. Und bei vielen rootless Usern kann es in/homeversteckt sein – das übersieht man leicht."
Verzeichnisse im Blick behalten
# Schnelle Übersicht welche Container-Verzeichnisse Platz belegen
du -sh /var/lib/containers/ 2>/dev/null
du -sh /var/lib/docker/ 2>/dev/null
du -sh /home/*/.local/share/containers/ 2>/dev/null
du -sh /run/containers/ 2>/dev/null
# Genauere Aufschlüsselung mit podman
podman system df # eigener Store
sudo podman system df # root Store
Was muss ins Backup?
| Was | Pfad | Backup nötig? |
|---|---|---|
| Podman Images (root) | /var/lib/containers/storage/ |
⚠️ nur wenn selbst gebaut |
| Podman Images (User) | ~/.local/share/containers/storage/ |
⚠️ nur wenn selbst gebaut |
| Podman Volumes (root) | /var/lib/containers/storage/volumes/ |
✅ ja – Anwendungsdaten |
| Podman Volumes (User) | ~/.local/share/containers/storage/volumes/ |
✅ ja – Anwendungsdaten |
| Bind Mounts | beliebiger Host-Pfad | ✅ ja – liegt wo du es hingelegt hast |
| Docker Images | /var/lib/docker/ |
⚠️ nur wenn selbst gebaut |
| Docker Volumes | /var/lib/docker/volumes/ |
✅ ja – Anwendungsdaten |
"Images müssen nicht gesichert werden wenn sie aus einer Registry gepullt werden können. Was wirklich gesichert werden muss sind Volumes und Bind-Mount-Pfade – dort liegen die Anwendungsdaten."
Root-Store vs. User-Store – das Problem
# Als root gepullt
sudo podman pull nginx
# Als teilnehmer01 eingeloggt
podman images
# → LEER. nginx ist nicht sichtbar.
Root und User sehen nicht dieselben Images. Was root pullt, ist für normale User unsichtbar – und umgekehrt.
Wo liegen die Stores genau?
# Deinen Store anzeigen
podman info | grep -A3 "graphRoot"
# Root-Store (nur mit sudo)
sudo podman info | grep -A3 "graphRoot"
Images zwischen Stores kopieren
# Image von root zu einem User kopieren
sudo podman image scp docker.io/library/nginx:latest teilnehmer01@::
# Image von User zu root kopieren (selten nötig)
podman image scp docker.io/library/nginx:latest root@::
"Das ist wie
cpzwischen/rootund/home/user– Podman kopiert die Layer rüber ohne erneuten Download."
2.10 Monitoring-Tools
podman stats
Ohne zusätzliche Tools direkt verfügbar:
podman stats --no-stream
# NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO
# mein-nginx 0.00% 6.2MB / 7.5GB 0.08% 0B / 0B 0B / 0B
Orientierungstabelle – "Was will ich wissen?"
| Frage | Befehl |
|---|---|
| Was läuft? | podman ps |
| Was läuft auch gestoppt? | podman ps -a |
| Wo sind die Logs? | podman logs <name> |
| Welcher User läuft im Container? | podman exec <name> id |
| Welche Ports? | podman port <name> |
| Welche Mounts? | podman inspect --format '{{.Mounts}}' <name> |
| Wie viel RAM/CPU? | podman stats --no-stream |
| Was hat sich verändert? | podman diff <name> |
| Welche Umgebungsvariablen? | podman inspect --format '{{.Config.Env}}' <name> |
| Welche IP hat der Container? | podman inspect --format '{{.NetworkSettings.IPAddress}}' <name> |
Übung 2 – nginx analysieren
🔴 Roter Faden: Wir analysieren unseren laufenden nginx aus Block 1.
Stelle sicher dass dein nginx läuft:
Aufgabe 2a – Überblick verschaffen
# Status, Ports, Image anzeigen
podman ps
podman inspect --format '{{.State.Status}}' mein-nginx
podman port mein-nginx
Fragen: 1. Welchen Status hat der Container? 2. Auf welchem Port ist nginx erreichbar?
Aufgabe 2b – In den Container einsteigen
podman exec -it mein-nginx bash
# Im Container:
id # Welcher User bin ich?
ps aux # Was läuft alles?
cat /etc/nginx/nginx.conf # nginx-Config anschauen
nginx -t # Config-Test
exit
Aufgabe 2c – Logs und Änderungen
# Etwas generieren – Seite aufrufen
curl http://localhost:${PORT}
# Logs anschauen
podman logs mein-nginx
podman logs --tail 5 mein-nginx
# Was hat sich verändert?
podman diff mein-nginx
Aufgabe 2d – Image-Store verstehen
# Deinen Store anzeigen
podman images
# Was liegt im Root-Store?
sudo podman images
# Sind die gleichen Images sichtbar?
Musterlösung Übung 2
2a
podman port mein-nginx
# 80/tcp -> 0.0.0.0:8100
podman inspect --format '{{.State.Status}}' mein-nginx
# running
2b
podman exec -it mein-nginx bash
id
# uid=0(root) gid=0(root) ← nginx läuft standardmässig als root im Container
# (In Block 7 schauen wir wie das mit rootless besser wird)
ps aux
# PID USER COMMAND
# 1 root nginx: master process nginx -g daemon off;
# 29 nginx nginx: worker process
nginx -t
# nginx: configuration file /etc/nginx/nginx.conf test is successful
2c
podman diff mein-nginx
# C /run
# C /var/cache/nginx
# A /var/cache/nginx/client_temp
# ...
# → nginx hat beim Start Verzeichnisse und PID-Files angelegt
2d
podman images
# docker.io/library/nginx latest ... 187MB
sudo podman images
# Möglicherweise andere Images oder gleiche – aber getrennte Stores
# → Root und User sehen nicht dieselbe Welt
Weiterführende Links
| Thema | Link |
|---|---|
| podman-ps Manpage | docs.podman.io/en/latest/markdown/podman-ps.1.html |
| podman-exec Manpage | docs.podman.io/en/latest/markdown/podman-exec.1.html |
| podman-inspect Manpage | docs.podman.io/en/latest/markdown/podman-inspect.1.html |
| Red Hat – Container untersuchen | access.redhat.com – Investigating and debugging containers |