Docker for Windows mit Podman ersetzen?

By Gerald Mücke | October 14, 2021

Docker for Windows mit Podman ersetzen?

In den letzten Monaten - oder Jahren - hat die alternative Container Engine der Open Container Initiative (OCI) - Podman - reichlich Zulauf bekommen, vor allem auch deshalb, weil grosse Distributoren wie ReadHat oder SuSe docker wegen Unsicherheiten hinsichtlich Lizenzmodell rausgeworfen und mit podman ersetzt haben. Ganz davon abgesehen, dass Podman eine der Container Engines von Kubernetes ist. Aber wie sieht die Situation in Windows aus?

In diesem Artikel möchte ich etwas Licht darauf werfen, wie Podman in Windows installiert wird und ob es zum jetzigen Zeitpunk auch eine Alternative für Docker4Windows sein kann.

Docker und Podman setzen beide auf Kernel Virtualisierung, die nur in Linux verfügbar ist und daher eine Linux Laufzeitumgebung erfordern - auch unter Windows. Frühere Versionen von Docker4Windows setzten dafür auf eine virtuelle Maschine, wie z.B. VirtualBox oder später Hyper-V. Die aktuelle Version läuft auch direkt im Windows Subsystem für Linux (WSL). Wie auch immer ihr Setup aussieht, sie brauchen Linux um podman oder docker zu laufen. Docker4Windows nimmt dabei einige der Konfigurationsschritte ab - bei podman ist etwas Handarbeit gefordert.

Während es bereits einige Blog Artikel oder Dokumentationen gibt, wie Podman in Linux oder WSL aufgesetzt werden, so beschreibt keiner davon, wie man Docker4Windows - und die damit verbundene User Experience - mit podman ersetzt, so dass man nahtlos aus dem Command Line Interface (CLI) podman Befehle ausführen kann.

Setup

Das Setup besteht aus den folgenden Schritten

  1. Starten der WSL distribution (z.B. Ubuntu)
  2. Installieren von Podman in WSL
  3. Installieren von OpenSSH in WSL und Generierung der Keys
  4. Services so einrichten, dass sie beim WSL Start automatisch Starten
  5. Installieren von Podman in Windows

Starten der WSL distro

In einer Command Shell, starten Sie WSL durch

wsl

Dadurch wird - sofern sie noch nicht läuft - das WSL gestart. Mit dem folgenden Befehl lassen sich alle installierten Distributionen auflisten

wsl --list

Was Ihnen eine Ausgabe wie folgt gibt

Windows-Subsystem for Linux-Distribution:
Ubuntu-20.04 (default)
docker-desktop
docker-desktop-data

Wie Sie sehen können, habe ich eine Ubuntu Distribution installiert und als Standard Distribution gesetzt, die automatisch gestartet wird wenn ich wsl ohne weitere Argumente starte. Die Ubuntu Distribution kann bequem über den Windows Store installiert werden.

Installieren von Podman in WSL

Nun, da WSL läuft, können wir Podman installieren. Weder Podman noch Docker laufen direkt in Windows sondern interagieren via Kommandozeile mit einem Prozess, der auf dem (entfernten) Linux System läuft. Auf einer lokalen Umgebung läuft dieser Prozess innerhalb der WSL.

Zunächst setzen wir ein paar Variablen, die so dass wir die Werte nur an einer Stelle definieren müssen.

export NAME=xUbuntu
export VERSION_ID=20.04
export WINDOWS_HOME=/mnt/c/Users/<yourUserNameHere>

Nun installieren wir Podman gemäss Dokumentation

sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/${NAME}_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/${NAME}_${VERSION_ID}/Release.key -O Release.key
sudo apt-key add - < Release.key
sudo apt-get update -qq
sudo apt-get -qq -y install podman
sudo mkdir -p /etc/containers
echo -e "[registries.search]\nregistries = ['docker.io', 'quay.io']" | sudo tee /etc/containers/registries.conf

Für den Fall, dass podman nicht als ihr angemeldeter User laufen soll, sondern als dedizierter podman user, müssen wir diesen noch anlegen. Sie können aber auch “ihren” Benutzer verwenden, der dann in den späteren Schritten entsprechend gesetzt werden muss.

sudo groupadd podman -g 2000
sudo useradd podman -u 2000 -g 2000
#add your user to podman group
sudo usermod -a -G podman $USER

Nun kümmern wir uns um den oben genannten Prozess.

Als Beispiel, wenn Sie eine Distribution mit Docker4Windows verwenden, sehen sie bei folgendem Aufruf

ps aux | grep docker

diese Ausgabe

root        48  5.9  0.0 1686676 31016 pts/0   Ssl+ 00:26  73:21 /mnt/wsl/docker-desktop/docker-desktop-proxy --distro-name Ubuntu-20.04 --docker-desktop-root /mnt/wsl/docker-desktop
gmuecke    111  4.4  0.0 766040 42520 pts/1    Ssl+ 00:26  55:09 docker serve --address unix:///home/gmuecke/.docker/run/docker-cli-api.sock

Der untere Prozess nimm die Aufrufe der CLI der “entfernten” Clients entgegen, d.h. die Docker Command Line Aufrufe. Podman benötigt dafür einen ähnlichen Prozess. Diesen können wir analog zu docker starten:

podman system service --time=0 unix:///home/gerald/podman.sock

Wie sie sehen, wird der Socket im Home meines Users angelegt.

Diesen Service wollen wir automatisch beim Start der WSL Distribution starten - ähnlich wie Docker. Da WSL kein systemd unterstützt, verwenden wir ein init.d Script.

Das nachfolgende Script muss als /etc/init.d/podman angelegt werden

#!/bin/bash

#you may use uid 1000 which is your local user or uid 2000 which is the 
# previously created podman user
PODMAN_USER=2000
BASEPATH=/run/user/$PODMAN_USER/podman
PID_FILE=$BASEPATH/podman.pid
SOCK_FILE=$BASEPATH/podman.sock

start() {
  mkdir -p $BASEPATH
  podman system service --time=0 unix://$SOCK_FILE &
  echo "$!" > $PID_FILE
  echo "podman service started, pid is $(cat $PID_FILE)"

  counter=0
  until [[ -S "$SOCK_FILE" && "$counter" -lt 5 ]]
  do
    echo "waiting 1 second"
    sleep 1
    counter=$((counter+1))
  done

  chown -R podman:podman $BASEPATH
  chmod g+rw $SOCK_FILE
}

stop() {
  if [ -S "$SOCK_FILE" ]; then
    echo "socket found"
  fi
  if [ -f "$PID_FILE" ]; then
    echo "pid file found, pid is $(cat $PID_FILE)"
  fi

  if [[ -S "$SOCK_FILE" && -f "$PID_FILE" ]]; then

       kill $(cat $PID_FILE)
       rm -f $SOCK_FILE
       rm -f $PID_FILE
  else
       echo "no socket found, Podman service seems to be stopped"
  fi
}

status() {
  pid=$(cat $PID_FILE)
  if [[ -S "$SOCK_FILE" && -f "$PID_FILE" && $(ps -p $pid > /dev/null) -eq 0 ]]; then
    echo "podman is running (PID=$pid)"
  else
    echo "podman is not running"
  fi

}

case "$1" in
    start)
       start
       ;;
    stop)
       stop
       ;;
    restart)
       stop
       start
       ;;
    status)
       status
       ;;
    *)
       echo "Usage: $0 {start|stop|status|restart}"
esac

Natürlich dürfen wir die Ausführungsberechtigungen nicht vergessen.

sudo chmod a+x /etc/init.d/podman

Nun starten wir den Service.

sudo service podman start

Installieren von OpenSSH in WSL und Generierung der Keys

Anders als Docker, das TCP Verbindungen auf dem daemon port zulässt, erfordert Podman eine remote SSH Verbindung. Um also das Podman CLI von Windows aus nutzen zu können, muss ein OpenSSH Server im WSL laufen.

Die Installation erfolgt (für Ubuntu) mittels

sudo apt-get -qq -y install openssh-server
sudo service ssh start

Ausserdem wollen wir die Authentication mit private/public Keys, d.h. password-less, einrichten, wofür wir ein private/public Schlüsselpaar erzeugen.

Innerhalb der WSL erzeugen wir das Schlüsselpar mit

export WINDOWS_HOME=/mnt/c/Users/Gerald/
ssh-keygen -b 2048 -t rsa -f $WINDOWS_HOME/.ssh/id_rsa_localhost -q -N ""
# also required for the local user
mkdir ~/.ssh
cat $WINDOWS_HOME/.ssh/id_rsa_localhost.pub >> ~/.ssh/authorized_keys

Mit dem letzten Schritt hinterlegen wir den Public Key als “Authorisierten Schlüssel” im WSL, der Private Schlüssel liegt im Windows User Home.

Services so einrichten, dass sie beim WSL Start automatisch Starten

Wir wollen, dass beim Starten des WSL der Podman Service und der OpenSSH Server automatisch starten. Dafür werden jedoch root-Rechte benötigt. Dafür erlauben wir das starten der Services als Root ohne Passwort, mit den folgenden Einträgen in der Sudoers Liste

sudo vi /etc/sudoers.d/01-services.conf

und fügen diese Einträge hinzu

%sudo   ALL(ALL) NOPASSWD: /usr/sbin/service ssh start
%sudo   ALL(ALL) NOPASSWD: /usr/sbin/service podman start

Nun erstellen wir ein Script, das beide Dienste startet

sudo vi /etc/wsl-init

mit diesem Inhalt

#!/bin/sh
echo booting
service ssh start
service podman start

und setzen zum Schluss die Ausführungs-Berechtigungen

sudo chmod +x /etc/wsl-init

Nachdem wir das Script erstellt haben, erzeugen wir auf dem Windows Host System eine “Geplante Aufgabe”, die beim Boot bzw. Anmelden ausgeführt wird und das WSL mit dem init Script startet - dies ist ebenso eine Aufgabe, die Docker4Windows einem abnimmt.

  1. In Windows, Öffne den Task Scheduler (Aufgabenplanung)
  2. Erzeuge eine “Einfache Aufgabe” / “Create Basic Task” (Wizard) - im Aktionsmenü
  3. Name: WSL Init
    • klick Weiter / Next
  4. Wähle Beim Anmelden / Run at login
    • klick Weiter / Next
  5. Wähle Aktion / Action:
    • Programm Starten / Start a Program
    • Programm: wsl
    • Argumente: -u root /etc/init-wsl
  6. Fertigstellen

Installieren von Podman in Windows

Nachdem wir Podman in der WSL installiert und die SSH Verbindung ermöglicht haben, ist es nun an der Zeit den Podman Client, d.h. das Command Line Interface, für Windows zu installieren.

Dafür kann der MSI Installer für podman von [https://github.com/containers/podman/releases/tag/latest] heruntergeladen werden.

Nach der Installation müssen wir nur den Endpunkt des Podman Service im WSL hinterlegen

set WSL_USER=<yourWslUserIDHere>
podman system connection add wsl --identity %USERPROFILE%\.ssh\id_rsa_localhost ssh://%WSL_USER%@localhost/run/user/2000/podman/podman.sock

Die 2000 ist die ID des podman Benutzers, setzen sie dort ggf. eine andere ID, falls Sie einen anderen Benutzer verwenden.

Die Konfiguration können wir mit

podman info

testen.

Fazit

Zum Zeitpunkt als ich diesen Artikel geschrieben habe, ist es durchaus möglich, Docker4Windows mit Podman zu setzen, jedoch gibt es ein paar Vorbehalte. Docker4Windows bringt eine automatisierte Installation und Konfiguration, sowie eine enge Integration des Dateisystems. Ausserdem sind - wir wir gesehen haben - einige manuelle Schritte für die Installation und vermutlich auch für die Aktualisierung erforderlich. Die SSH Verbindung “fühlt” sich etwas langsamer an, das kann jedoch täuschen. Viel gewichtiger ist hier die Integration ins Dateisystem. Während Docker die Übersetzung von Windows Pfaden ins WSL automatisch übernimmt, muss dies mit Podman manuell passieren (z.B: mit wslpath)

Für Docker4Windows wird spätestens ab Anfang 2022 eine Lizenzgebühr fällig, falls ihre Firma eine bestimmte Grösse oder Umsatz überschreitet. Zum Zeitpunk des Schreibens liegen diese Grenzen bei > 250 Angestellte ODER > 10M$ Umsatz. Die Kosten für kleine Teams liegen bei 7$/Person/Monat oder 84$/Person/Jahr. Im Gegenzug erhält eine nahezu schmerzfreie Installationserfahrung, Automatische Updates und eine gute Integration von Docker in Windows.

Podman ist hinsichtlich Container-Features praktisch ein vollwertiger Ersatz, um Container auf Linux laufen zu lassen (Docker-Compose ausgenommen). Auf Windows Umgebungen, ist das jedoch mit einigen Mehraufwänden verbunden. Die Frage, ob der Mehraufwand 84$ pro Person und Jahr überwiegt oder nicht, muss jeder für sich selbst beantworten. Ich habe jedoch Zweifel, dass die Rechnung im Moment aufgeht. Das kann sich zu einem späteren Zeitpunkt jedoch ändern. Im Moment würde ich daher bei Docker4Windows bleiben.

Referenzen