Wie Container-Werkzeug unter Windows wirklich läuft – ein Client
im PATH (Programmsuchpfad), der über SSH (Secure Shell) mit einem Linux redet: entweder der WSL2-Maschine auf dem Laptop
oder einem Server bei Hetzner. Mit Bezug auf diese Installation, dem Umschalten
zwischen lokal und Server, und der Frage „warum sehe ich meine Images nicht?“.
Windows 10 · podman 6.0.2WSL2 (Windows Subsystem for Linux 2) · rootlessStand: 31. August 2026
01 Deine Installation
Der Ist-Zustand auf dem Laptop – damit die restlichen Abschnitte konkret sind.
Podmanpodman 6.0.2, per winget (Paket Podman.CLI). Update auf 6.1.0 verfügbar: winget upgrade Podman.CLI.
DockerNicht installiert. Kein docker-Befehl im PATH, kein Docker Desktop.
Composepodman-compose via scoop (Python). podman compose … ruft es automatisch auf.
Connectionsdrei Stk. – podman-machine-default (lokal, rootless, Default), podman-machine-default-root (lokal, rootful), hetzner (Remote-Server, wird von cloud.ps1 angelegt).
WSL-Distrospodman-machine-default (von Podman verwaltet) und ein separates Ubuntu (unabhängig, aktuell gestoppt).
In einem Satz
Du hast Podman lokal (in einer kleinen Linux-VM) und kein Docker.
Für dieses Repo ist das genau richtig – der Laptop ist nur Fernbedienung, die
Container laufen auf dem Server.
02 Wie Podman unter Windows läuft
Container brauchen einen Linux-Kernel. Windows hat keinen – also läuft
immer irgendwo ein Linux, und podman.exe ist nur der Client davor.
Der Unterschied, aus dem sich fast alles Weitere ergibt: wie viele Kerne laufen hier eigentlich?
Ein Container ist keine kleine VM. Er ist ein Prozess auf dem Kernel des
Wirts, dem man eine eigene Sicht auf Dateisystem, Netz und Prozessliste gegeben hat. Das macht
ihn schnell und klein – und erklärt zugleich, warum ein Zugriff auf den
Container-Socket gleichbedeutend mit Root auf dem Wirt ist.
Teil
Wo
Aufgabe
podman.exe
Windows, im PATH
Der Client. Nimmt deine Befehle entgegen, schickt sie per SSH / API-Socket an ein Linux und zeigt das Ergebnis. Baut selbst keine Container.
Podman-Maschine
WSL2-VM (podman-machine-default)
Ein schlankes Linux (Fedora CoreOS-artig) in WSL. Hier laufen die Container, hier liegen die Images. Startet nicht automatisch mit Windows.
Remote-Host
Hetzner-Server
Optional dasselbe wie die Maschine, nur in der Cloud. Der Client redet per SSH zum podman.socket dort.
Podman Desktop
Windows (optional)
Grafische Oberfläche über denselben Client – separat: winget install RedHat.Podman-Desktop. Nicht nötig, aber bequem fürs Draufschauen.
Kein Daemon. Anders als Docker läuft bei Podman kein
Hintergrunddienst als root. Jeder podman-Aufruf startet kurz einen Prozess,
macht seine Arbeit, ist weg. Das ist der Grund, warum es „rootless“ kann und warum
ein abgestürzter Daemon nie das Problem ist – es gibt keinen.
Merksatz
podman ... auf dem Laptop tut nichts lokal – es fragt die gerade
als Default gesetzte Connection. Ist das die Maschine, siehst du Laptop-Container. Ist
es hetzner, siehst du die vom Server. Das ist die häufigste
Verwirrung – Abschnitt 5.
03 Rootless: als dein User, nicht als root
Deine Maschine läuft rootless – der Normalfall bei Podman. Das
prägt, wie Ports, Dateirechte und ein paar Images sich verhalten.
Was das heißt
Container-Prozesse laufen mit deinen Rechten, nicht als root.
Es gibt keinen privilegierten Dienst dazwischen – nichts, was ein Angreifer aus einem
Container heraus übernehmen könnte, um dann als root auf dem Host zu sitzen. Ein
Ausbruch landet bestenfalls bei deinem Benutzerkonto.
Wie es funktioniert – User-Namespaces
Innerhalb des Containers gibt es root (UID 0), aber das ist eine
Illusion: UID (User Identifier) 0 im Container = dein User auf dem Host. Alle anderen Container-UIDs werden
auf einen dir zugeteilten Bereich abgebildet (aus /etc/subuid /
/etc/subgid, meist 65 536 IDs ab 100000). Nachsehen:
Laptop · PowerShell
podman machine ssh cat /etc/subuid # dein zugeteilter UID-Bereich
podman unshare cat /proc/self/uid_map # die Abbildung Container -> Host
podman info --format "{{.Host.Security.Rootless}}" # true
Die drei Folgen im Alltag
Thema
Was rootless anders macht
Ports < 1024
Ein normaler User darf sie nicht binden. In der Podman-Maschine ist net.ipv4.ip_unprivileged_port_start=80 meist schon gesetzt, dann geht -p 80:80. Sonst: hoher Port (-p 8080:80) + Reverse Proxy, oder auf einem Server den sysctl setzen (macht die Container-Host-Anleitung).
Datei-Eigentümer in Volumes
Schreibt der Container als „root“, gehört die Datei auf dem Host dir. Schreibt er als UID 33 (www-data), gehört sie einer hohen Host-UID wie 100032 – sieht „fremd“ aus, ist normal. Rechte anpassen: podman unshare chown -R 33:33 ./data oder Mount mit :U.
Images, die echtes root wollen
Selten – manche System-Container (systemd drin), alte Software. Dann rootful fahren: podman --connection podman-machine-default-root run … lokal, oder sudo podman auf einem Server.
rootless und rootful sind getrennte Welten
Die Connection podman-machine-default (rootless) und
podman-machine-default-root (rootful) haben eigene Images,
Container und Volumes. Was du rootless gebaut hast, sieht rootless-podman –
sudo podman bzw. die -root-Connection sieht es nicht, und
umgekehrt. „Mein Image ist weg“ liegt oft nur daran, dass man versehentlich die
andere Seite fragt.
Auf dem Hetzner-Server
Die cloud-init.yaml aktiviert podman.socket als
System-Socket – die hetzner-Connection zeigt also auf
root@…, dort läuft Podman rootful. Für einen
Wegwerf-Server mit einem Zweck ist das ok. Die Sicherheits-Vorteile von rootless holt man
sich eher auf einem Host, der länger steht (siehe
Server-Hardening).
04 Die Podman-Maschine steuern
Die lokale Linux-VM. Ein paar Befehle reichen für den Alltag.
Laptop · PowerShell
podman machine list # welche Maschinen, laufen sie?
podman machine start # die (einzige) Maschine hochfahren
podman machine stop # runterfahren (Container werden gestoppt)
podman machine ssh # Shell in die VM
podman machine info # CPU/RAM/Disk, Podman-Version drin
Nach jedem Windows-Neustart oder Ruhezustand ist die Maschine oft aus
(oder halb da – siehe Troubleshooting). Erst
podman machine start, dann arbeiten.
Ressourcen ändern
Deine Maschine hat 2 GiB RAM – für ein, zwei Test-Container
ok, für einen lokalen Stack (Datenbank + App + Proxy) schnell zu wenig. Anpassen geht nur
bei gestoppter Maschine:
Laptop · PowerShell
podman machine stop
podman machine set --cpus 4 --memory 4096 # RAM auf 4 GiB
podman machine set --disk-size 120 # Disk NUR vergroessern, nie kleiner
podman machine start
Neu aufsetzen
Wenn die Maschine kaputt ist, ist sie schnell ersetzt (Images/Container darin sind dann
weg – die auf dem Server nicht):
In der VM (virtuelle Maschine) unter ~/.local/share/containers/storage (rootless). Nach Windows
durchgereicht wird das nicht als Ordner – es steckt in der WSL-Disk
(ext4.vhdx unter %LOCALAPPDATA%\containers\podman\machine\wsl).
Reinschauen: podman machine ssh, dann normale Linux-Befehle. Platz prüfen:
podman system df.
05 Connections: lokal ↔ Server umschalten
Der Punkt, der dich zweimal erwischt hat. Eine Connection ist ein
benanntes Ziel (Adresse + SSH-Key). Eine davon ist Default – die fragt
jeder podman-Befehl ohne --connection.
Laptop · PowerShell
podman system connection list
Name
Ziel
Wann
podman-machine-default
lokale VM, rootless
Der Normalfall. Deine Laptop-Container.
podman-machine-default-root
lokale VM, als root
Nur wenn du Ports < 1024 ohne Extra-Config brauchst oder etwas root verlangt.
hetzner
ssh://root@<server-ip>
Zeigt auf den Cloud-Server. Legt cloud.ps1 beim up an und macht sie zum Default.
Umschalten
Laptop · PowerShell
# dauerhaft: Default setzen
podman system connection default podman-machine-default # zurueck auf lokal
podman system connection default hetzner # auf den Server# einmalig, ohne den Default zu aendern
podman --connection podman-machine-default images
podman -c hetzner ps
Die Falle nach cloud.ps1
.\scripts\cloud.ps1 up setzt den Default auf hetzner. Ab da zeigt
podman images die Images auf dem Server, nicht die vom Laptop
– das ist Absicht, damit podman build/run auf dem Server
landen.
Nach cloud.ps1 down ist der Server gelöscht, die Connection
hetzner zeigt aber weiter ins Leere – podman images
hängt dann in einen SSH-Timeout. Neuere Fassung des Skripts stellt den Default beim
down automatisch auf die lokale Maschine zurück. Sonst von Hand:
podman system connection default podman-machine-default.
06 Images & Container ansehen
Die Alltagsbefehle. Alle gehen an die Default-Connection – erst prüfen,
worauf die zeigt (Abschnitt 5).
Laptop · PowerShell
podman images # heruntergeladene/gebaute Images
podman ps # laufende Container
podman ps -a # auch gestoppte
podman pull docker.io/library/nginx:alpine
podman run --rm -p 8080:80 nginx:alpine # http://localhost:8080
podman build -t mein-image . # aus dem Containerfile/Dockerfile hier
podman system df # Speicher: Images / Container / Volumes
podman image prune # baumelnde Images weg
podman system prune -a # alles Ungenutzte weg (Vorsicht)
podman rmi <image> # ein Image loeschen
Schnelltest „alles ok“
podman run --rm docker.io/library/hello-world – lädt ein winziges
Image und gibt einen Grußtext aus. Klappt das, stimmt die ganze Kette (Client →
Maschine → Netz).
Grafisch: Podman Desktop (winget install RedHat.Podman-Desktop)
zeigt Images, Container, Volumes und Logs in einem Fenster – und hängt sich an
dieselben Connections, also auch an hetzner.
07 Podman vs. Docker
Die CLI (Command-Line Interface) ist zu >95 % deckungsgleich – docker run…
wird zu podman run…. Die Unterschiede darunter:
Warum Daten im Container verschwinden, was ein Tag wirklich ist, und wieso ein Rebuild oft Sekunden dauert.
Das Image ist unveränderlich, der Container ist vergänglich. Alles,
was ein Container schreibt, landet in einer dünnen Schicht obendrauf, die mit ihm
verschwindet. Wer das verinnerlicht hat, versteht ohne weitere Erklärung, warum es Volumes
gibt, warum ein Tag sich ändern muss und warum Container-Images so klein sein können.
podman compose braucht podman-composeoderdocker-compose als Provider. Alternativ Pods / Quadlet / kube play.
docker compose eingebaut (Plugin)
Pods
ja – mehrere Container teilen ein Netz-Namespace, wie ein Kubernetes-Pod. podman kube generate/play.
nein (nur Compose-„Services“)
Autostart
über systemd / Quadlet (.container-Dateien) – sauber, kein --restart-Hack nötig
--restart=always über den Daemon
Docker-API
podman system service stellt einen Docker-kompatiblen Socket bereit – Tools, die DOCKER_HOST erwarten, funktionieren
ist die Referenz
Lizenz
Apache 2.0, komplett frei – auch die GUI (Graphical User Interface)
Engine frei, Docker Desktop ab größerer Firma kostenpflichtig
Für dieses Repo
Die Container-Host-Anleitung
hat einen Umschalter Podman/Docker. Auf dem Server ist die Wahl fast egal –
Podman ist Vorgabe, weil rootless + Quadlet gut zum „Server wegwerfen“-Ansatz
passen. Auf dem Laptop brauchst du keins von beiden zwingend. Podman ist da, das
reicht als Client.
08 Wenn du Docker lokal brauchst
Etwa weil ein Tool hart docker erwartet oder eine Anleitung
docker compose nutzt. Vier Wege, von leicht nach schwer:
Derselbe Befehlssatz, ein grundlegend anderer Aufbau – und warum das für den Jenkins-Server wichtig war.
Derselbe Befehlssatz, ein anderer Aufbau.alias docker=podman
funktioniert für den Alltag – die Unterschiede zeigen sich erst dort, wo es um
Rechte, Neustarts und Werkzeuge geht, die einen Daemon erwarten. Genau diese drei Stellen sind
es, an denen die Anleitungen dieser Sammlung nachhelfen müssen.
Weg
Womit
Anmerkung
Nur die docker-CLI, Backend Podman
scoop install docker + podman system service --time=0 & in der Maschine, dann $env:DOCKER_HOST auf den Podman-Socket
Kein zweites System. docker und podman reden mit derselben VM.
Rancher Desktop
winget install suse.RancherDesktop
Frei. Bringt echten dockerd (oder containerd) in WSL2, plus kubectl/k3s. Guter Docker-Desktop-Ersatz.
Docker Desktop
winget install Docker.DockerDesktop
Am einfachsten, aber: Lizenz prüfen (ab ~250 MA / >10 Mio $ Umsatz kostenpflichtig). Läuft parallel zur Podman-Maschine, frisst RAM.
Docker Engine in der Ubuntu-Distro
in wsl -d Ubuntu: curl -fsSL https://get.docker.com | sh
Deine Ubuntu-Distro ist schon da. Kein Windows-Integrationskomfort, aber voll unter Kontrolle.
Empfehlung
Für dieses Repo: nichts davon installieren. Wenn eine Anleitung
docker compose zeigt, läuft das auf dem Server (dort ist Docker
oder Podman via cloud-init.docker.yaml installiert). Brauchst du's doch lokal,
nimm Zeile 1 (nur die CLI) – am wenigsten Ballast.
09 Einen Docker-Server vom Laptop steuern
Analog zur hetzner-Podman-Connection, nur für Docker.
Laptop · PowerShell
# Docker-Client (falls installiert) an den Server haengen
docker context create hetzner --docker "host=ssh://root@<server-ip>"
docker context use hetzner
docker ps # Container auf dem Server# oder nur fuer einen Befehl
$env:DOCKER_HOST = "ssh://root@<server-ip>"; docker compose up -d
Voraussetzung ist derselbe SSH-Key wie für hcloud / die Podman-Connection
(~/.ssh/id_ed25519, beim Server hinterlegt – siehe
Server-Basis).
Der Mehrere-Dienste-Guide
und scripts/dienste-stack.ps1 machen genau das per SSH.
+ Wenn „Cannot connect to Podman“ kommt
Die Meldung unable to connect to Podman socket … connectex: No
connection could be made heißt: der Client erreicht das Linux nicht.
Zeigt die Connection irgendwohin Totes?podman system connection list – steht der Default auf hetzner
und der Server ist unten/gelöscht, ist das die Ursache:
podman system connection default podman-machine-default.
Läuft die Maschine wirklich?podman machine list.
Steht dort nicht laufend: podman machine start.
Maschine „läuft“, Verbindung trotzdem tot (dein Fall
neulich: wsl -l -v zeigt sie als Running, aber
127.0.0.1:<port> refused). Der SSH-Portforward ist nach dem Ruhezustand
hängen geblieben. Neu aufsetzen des Tunnels:
Laptop · PowerShell
podman machine stop
podman machine start
Hilft das nicht: wsl --shutdown (schließt alle Distros!), dann
podman machine start.
WSL selbst zickt (WSL 2 requires an update o.ä.):
wsl --update, danach podman machine start. Ganz selten:
Virtualisierung im BIOS / Windows-Feature „VM-Plattform“ prüfen.
Immer noch kaputt – Maschine wegwerfen und neu (Abschnitt 4,
„Neu aufsetzen“). Lokale Images sind dann weg, sonst nichts.
Vorbeugen
Nach jedem Laptop-Start einmal podman machine start (ist die Maschine schon
da, kommt nur eine kurze Meldung). Wer's automatisch will: eine Aufgabenplanung bei
Anmeldung, analog zu scripts/install-autodown.ps1.
+ Bezug zu den Skripten
Was ghcr.io ist, warum drei verschiedene Registries im Spiel sind – und warum eine davon zwei Adressen hat.
Ein Lager, kein Dienst. Die Registry speichert Schichten unter ihrer
Prüfsumme und Manifeste unter einem Namen – mehr nicht. Welche man nimmt, ist eine
Frage von Anmeldung, Erreichbarkeit und Abrufgrenzen: ghcr.io für die eigenen
Images, docker.io für fremde, die Cluster-Registry für alles, was den
Laptop nicht verlassen soll.
scripts/cloud.ps1 up baut den Server, legt die hetzner-Connection
an und macht sie zum Podman-Default – danach landen podman-Befehle auf
dem Server.
-CloudInit cloud-init.docker.yaml baut den Server stattdessen mit Docker
(siehe Container-Host).
Die hetzner-Podman-Connection zeigt dann auf einen Server ohnepodman.socket – dort per ssh / docker context
arbeiten (Abschnitt 9).
cloud.ps1 down löscht den Server. Danach den Podman-Default
zurück auf podman-machine-default (neuere Skript-Fassung macht das
selbst).
scripts/dienste-stack.ps1 steuert Docker-Compose-Stacks auf dem Server
– komplett per SSH, ohne lokalen Docker-Client.
Alle Angaben Stand August 2026, podman 6.
Preise/Server: Kosten & Budget.