Docker läuft als Dienst mit Root-Rechten. Wer in die Docker-Gruppe darf, kann sich damit praktisch zum Systemverwalter machen, das ist kein Geheimnis, sondern dokumentiertes Verhalten. Podman geht den anderen Weg: kein dauerhafter Dienst, und Container laufen als der Benutzer, der sie startet.
Für einen Server, auf dem mehrere Dinge nebeneinander laufen, ist das ein echter Unterschied. Der Umstieg ist an drei Stellen unbequem, und die stehen weiter unten.
Was sich sofort ändert#
| Docker | Podman rootless | |
|---|---|---|
| Hintergrunddienst | ja, als root | keiner |
| Container läuft als | root (meist) | dein Benutzer |
| „root“ im Container | ist Host-root, wenn es ausbricht | ist dein Benutzer auf dem Host |
| Start beim Systemstart | Docker-Dienst | systemd-Unit des Benutzers |
| Ports unter 1024 | erlaubt | gesperrt, bis konfiguriert |
| Befehle | docker … | podman …, weitgehend identisch |
apt install podman
podman info | grep -E "rootless|graphDriver"
podman run --rm -it alpine id
# uid=0(root) — im Container. Auf dem Host ist es dein Benutzer.
Das ist der Kern: Der Bruch aus dem Container endet bei deinem Benutzerkonto, nicht bei root.
Stelle 1: Ports unter 1024#
Ein unprivilegierter Benutzer darf sie nicht belegen. Zwei saubere Wege:
# A: Reverse-Proxy als Systemdienst davor, Container lauscht auf hohem Port
# (der empfohlene Weg — siehe /beitraege/reverse-proxy-caddy-nginx)
# B: Untergrenze systemweit senken
echo "net.ipv4.ip_unprivileged_port_start=80" > /etc/sysctl.d/99-podman.conf
sysctl --system
Variante A ist die bessere, weil ohnehin ein Proxy mit Zertifikat davor gehört.
Stelle 2: Volumes und Dateirechte#
Rootless-Container bilden Benutzerkennungen ab: Root im Container ist dein Benutzer auf dem Host, Benutzer 1000 im Container ist irgendeine hohe Kennung im Subuid-Bereich. Wer ein Host-Verzeichnis einhängt, bekommt deshalb regelmäßig „permission denied“.
cat /etc/subuid /etc/subgid # dein Bereich, meist 100000+
# Podman die Rechte beim Einhängen anpassen lassen:
podman run -v /srv/daten:/daten:U ...
# Oder nachträglich in den Benutzer-Namensraum wechseln und umschreiben:
podman unshare chown -R 1000:1000 /srv/daten
Der naheliegende Reflex, chown -R 100999:100999 /srv/daten als root, funktioniert und ist trotzdem falsch: Die Zahl gilt nur für diesen Benutzer und dieses Abbild. Nach einem Neuaufsetzen stimmt sie nicht mehr. podman unshare rechnet sie jedes Mal richtig aus.
Benannte Volumes umgehen das Problem ganz, sie liegen unter ~/.local/share/containers/ und gehören von vornherein dir.
Stelle 3: der Start beim Hochfahren#
Hier hat sich der Weg geändert. podman generate systemd gilt als überholt; der aktuelle Weg heißt Quadlet: Du schreibst eine Beschreibungsdatei, systemd erzeugt daraus die Unit.
# ~/.config/containers/systemd/vaultwarden.container
[Unit]
Description=Vaultwarden
[Container]
Image=docker.io/vaultwarden/server:latest
PublishPort=127.0.0.1:8222:80
Volume=vaultwarden-daten:/data
Environment=SIGNUPS_ALLOWED=false
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user start vaultwarden
systemctl --user status vaultwarden
journalctl --user -u vaultwarden -f
Benutzerdienste laufen normalerweise nur, solange der Benutzer angemeldet ist. Ein Container, der nach dem Schließen der SSH-Sitzung stirbt, ist genau das, kein Fehler, sondern die Voreinstellung. Ein Befehl behebt es:
loginctl enable-linger $USER
loginctl show-user $USER | grep Linger # Linger=yes
Updates automatisch, aber kontrolliert#
Mit AutoUpdate=registry prüft Podman regelmäßig auf neue Abbilder und fährt bei einem fehlgeschlagenen Start automatisch auf das vorherige zurück. Das ist gegenüber einem blinden docker compose pull ein echter Gewinn.
systemctl --user enable --now podman-auto-update.timer
podman auto-update --dry-run
Ob automatische Updates überhaupt eine gute Idee sind, hängt vom Dienst ab, die Abwägung steht in Container-Updates und Images.
Compose weiterbenutzen#
Bestehende compose.yaml-Dateien müssen nicht weg:
# Variante 1: Podman spricht die Docker-Schnittstelle
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker compose up -d
# Variante 2: podman-compose
apt install podman-compose && podman-compose up -d
Beides funktioniert für den Alltag. Für dauerhaft betriebene Dienste sind Quadlet-Units trotzdem die bessere Wahl: Sie sind systemd-Einheiten mit Abhängigkeiten, Protokoll und Neustartverhalten, kein zweites Verwaltungssystem daneben.
Wo Podman nicht passt#
- Werkzeuge, die fest die Docker-Schnittstelle erwarten, manche CI-Systeme und Verwaltungsoberflächen. Der Socket hilft oft, aber nicht immer.
- Dienste, die echte Root-Rechte im Netz brauchen (bestimmte VPN- und Netzwerkwerkzeuge). Dafür gibt es Podman auch mit Root, dann ist der Sicherheitsgewinn allerdings weg.
- Wenn im Team alle Docker sprechen. Der Unterschied kostet Erklärzeit bei jedem Handgriff.
- Sehr schreibintensive Container auf älteren Systemen ohne native Overlay-Unterstützung im Benutzermodus.
Häufige Fragen#
Kann ich Docker und Podman parallel betreiben?#
Ja. Sie teilen sich weder Abbilder noch Netze, und beide belegen Ports, Konflikte sind also möglich, aber sichtbar.
Sind die Abbilder dieselben?#
Ja, es ist dasselbe Format. Podman zieht standardmäßig aus mehreren Quellen; deshalb gehört der volle Name (docker.io/bibliothek/abbild) in die Konfiguration, sonst ist nicht eindeutig, was geladen wird.
Was ist ein Pod?#
Mehrere Container, die sich einen Netz-Namensraum teilen, sie erreichen sich über localhost. Praktisch für eine Anwendung mit Beiwagen-Container, und dasselbe Konzept wie in Kubernetes.
Läuft das auch in einem LXC-Container unter Proxmox?#
Ja, in einem unprivilegierten LXC mit den passenden Optionen. Ob das der richtige Aufbau ist, hängt an derselben Frage wie immer: LXC oder VM.
Lohnt der Umstieg auf einem Server, der schon läuft?#
Selten sofort. Der pragmatische Weg: neue Dienste mit Podman aufsetzen, bestehende laufen lassen und beim nächsten größeren Umbau mitnehmen.
Kurz gesagt#
- Rootless heißt: Ein Ausbruch endet bei deinem Benutzer, nicht bei root.
- Ports unter 1024 brauchen einen Proxy davor oder eine sysctl-Änderung.
- Volumes mit
:Uoderpodman unshare chownbehandeln, nie mitchownals root. - Quadlet statt
generate systemd, undloginctl enable-lingernicht vergessen. AutoUpdate=registrykann bei Fehlstart zurückrollen, das kann Docker so nicht.
Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.