Neuigkeiten von trion.
Immer gut informiert.

buildah: Docker und Kubernetes Images ohne Daemon

buildah

Docker ist die führende Umsetzung von Linux Containern - kein Wunder, hat Docker die Idee von Containern als leichtgewichtige Alternative zu Virtualisierung erst populär gemacht. Inzwischen hat sich das Ökosystem deutlich weiterentwickelt. Google hat mit dem Kubernetes Projekt den defacto Standard für Scheduling und Verwaltung von Containern und zugehörigen Resourcen geschaffen. Neben Docker existieren mit rkt (CoreOS) und CRI-O (Open Container Initiative) weitere Container Runtimes für das mittlerweile gesetzte OCI Image Format. Relativ neu dabei sind die Werkzeuge buildah zum Bauen von Containern und podman zur Ausführung mittels CRI-O (beide von Project Atomic, RedHat).

Warum entstehen unterschiedliche Runtimes und Build-Toolchains? Welche Vorteil für Nutzer im Kontext von Docker oder Kubernetes ergeben sich daraus?

Im Gegensatz zu Docker zeichnet sich rkt dadurch aus, dass kein zusätzlicher Dämon benötigt wird. Bei buildah und podman werden die Verantwortlichkeiten stärker separiert: Docker ist eine All-In-One-Lösung, die sowohl Netzwerk als auch Image-Erzeugung und Container Runtime beeinhaltet. Weiterentwicklungen führen dann sehr schnell zu API-Brüchen, die vor allem in der Anfangszeit für Nutzer und insbesondere Werkzeughersteller schwierig zu handhaben waren. Bei buildah ist die Motivation ohne separaten Daemon auszukommen und mit klassischen Werkzeugen der Kommandozeile wie cp und make zum Ziel zu gelangen. Ein Zwang zur Nutzung von Dockerfiles entfällt damit, und bestehende Scripts und Konfigurationsmanagement kann auch für Container Images eingesetzt werden. Damit soll die Integration in bestehende Buildprozesse und Umgebungen erleichtert werden. Da kein Daemon existiert, müssen somit auch keine besonderen Kniffe angewendet werden, um beispielsweise in einem Container, wie in einem Kubernetes-Cluster, wiederum Images zu erstellen.

Ein schneller Blick auf buildah mit Ubuntu 18.04 ist leider nicht möglich - aktuell gibt es lediglich Pakete für Ubuntu 16.04 über das PPA von Project Atomic: https://launchpad.net/~projectatomic/+archive/ubuntu/ppa Bei RedHat, Fedora und CentOS sieht es, wie bei einem RedHat Projekt zu erwarten ist, besser aus: Ein yum install -y buildah bzw. dnf install -y buildah reicht hier aus.

Alternativ ist natürlich eine Installation auf Basis der Sourcen möglich, Details dazu finden sich hier: https://github.com/projectatomic/buildah/blob/master/install.md

Damit ist die Installation von buildah und podman unter Ubuntu sehr einfach:

$ sudo add-apt-repository ppa:projectatomic/ppa
$ sudo apt-get update
$ sudo apt-get install buildah

Anschließend kann buildah verwendet werden, um auf Basis eines Dockerfile ein Image zu bauen. Zunächst wird für das Image ein Dockerfile benötigt:

FROM ubuntu:latest
RUN apt-get update
RUN apt-get install -y fortune

CMD ["/usr/games/fortune"]

Damit Base-Images von DockerHub bezogen werden können, ist DockerHub als entsprechende Registry für buildah in /etc/containers/registries.conf einzutragen:

[registries.search]
registries = ['docker.io']

[registries.insecure]
registries = []

[registries.block]
registries = []

Zu beachten ist, dass buildah als root laufen muss, daher werden die Beispiele mit sudo gezeigt. Steht kein runc als Container-Laufzeitumgebung zur Verfügung, kann diese durch die Environmentvariable BUILDAH_RUNTIME spezifiziert werden. Die buildah Paketabhängigkeiten bringen eine runc Implementierung in Form von CRI-O runc mit.

Mittels buildah kann nun das Image gebaut werden.

$ sudo BUILDAH_RUNTIME=/usr/lib/cri-o-runc/sbin/runc \
   buildah build-using-dockerfile -t fortune .
STEP 1: FROM ubuntu:latest
Getting image source signatures
Copying blob sha256:6b98dfc1607190243b0938e62c5ba2b7daedf2c56d7825dfb835208344705641
 29.81 MiB / 29.81 MiB [====================================================] 2s
Copying blob sha256:4001a1209541c37465e524db0b9bb20744ceb319e8303ebec3259fc8317e2dec
 843 B / 843 B [============================================================] 0s
Copying blob sha256:6319fc68c576d6bd3e469b0ae31e9a010bc9b71ed286cf4e632424d82dca70d8
...
Writing manifest to image destination
Storing signatures
ca76d9d1752e587471a7d37bbce6877e7f498cd408177a9c53bd9dec4e2cc693

Das erstellte Image liegt anschließend unter /var/lib/containers.

Vorhandene Images können auch mit buildah angezeigt werden:

$ sudo buildah images
IMAGE ID       IMAGE NAME                       CREATED AT          SIZE
113a43faa138   docker.io/library/ubuntu:latest  Jun 5, 2018 21:20   83.7 MB
ca76d9d1752e   localhost/fortune:latest         Jun 18, 2018 19:23  127 MB

Als Ergänzung zu buildah gibt es das Werkzeug podman. Mit podman können Images analog zu docker run als Container ausgeführt werden. Das gebaute Image kann auch zu einer Docker-Registry oder einem Docker-Daemon gepusht werden. Letzteres kann zum Beispiel sinnvoll sein, wenn man Build-Slaves verwendet, und diese erfolgreich gebaute Images einem Docker-Daemon zur Verfügung stellen sollen. Eine Registry kann zum Beispiel im Kubernetes Kontext sinnvoll sein, wenn die Images dann in einem Cluster durch Kubernetes Nodes zur Ausführung bezogen werden. Somit stellt buildah in diesem Kontext eine Alternative zum häufig eingesetzten Docker-in-Docker (DinD) dar.

Als Beispiel die Ausführung des mit buildah erzeugen Image durch podman:

$ sudo podman run fortune
You will be called upon to help a friend in trouble.

Das Image kann nun auch zu einem Docker-Daemon oder einer Registry gepusht werden:

$ sudo buildah push fortune docker-daemon:fortune:latest

Wer mit buildah und podman schnelle Experimente machen möchte, kann auf das folgende Vagrantfile zurückgreifen. Es verwendet ein Ubuntu 16.04 Basisimage und installiert darauf dann buildah und podman.

Vagrantfile für Ubuntu und buildah:

Vagrant.require_version ">= 1.8"

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"

  config.vm.provider :virtualbox do |vb|
    vb.linked_clone = true
    vb.name = "buildah demo"
    vb.customize ["modifyvm", :id, "--memory", "4096"]
    vb.customize ["modifyvm", :id, "--cpus", 2]
  end

  $setup = <<SCRIPT
sudo add-apt-repository -y ppa:projectatomic/ppa
sudo apt-get update
sudo apt-get install -y buildah podman
SCRIPT
  config.vm.provision "shell", inline: $setup

end

Zusammen mit Vagrant lässt sich nun sehr schnell eine Experimentierumgebung für buildah erstellen:

$ vagrant up
$ vagrant ssh
vagrant@ubuntu-xenial:~$ sudo su -
vagrant@ubuntu-xenial:~# buildah -v
buildah version 1.2-dev (image-spec 1.0.0, runtime-spec 1.0.0)

Prinzipiell kann buildah auch innerhalb eines Docker Containers laufen. Dieser muss dann jedoch mit erweiterten Rechten gestartet werden, um Zugriff auf die Container Mechanismen des Linux Kernel zu erhalten. Außerdem muss das Verzeichnis /var/lib/containers durch ein Filesystem bereitgestellt werden, dass außerhalb des Docker-Overlay-Filesystem liegt, da es sonst Konflikte gibt.

Im Beispiel ist zu sehen, wie buildah in Docker ausgeführt werden kann:

$ docker run --rm --privileged -v /tmp/containers:/var/lib/containers -it fedora bash
[root@50a40f6424b9 /]# yum install -y buildah
[root@50a40f6424b9 /]# buildah -version
buildah version 1.1 (image-spec 1.0.0, runtime-spec 1.0.0)
[root@50a40f6424b9 /]# buildah build-using-dockerfile -t fortune .
STEP 1: FROM ubuntu:latest
Getting image source signatures
...
Writing manifest to image destination
Storing signatures
[root@50a40f6424b9 /]# buildah images
IMAGE ID   IMAGE NAME                       CREATED AT           SIZE
113a43faa  docker.io/library/ubuntu:latest  Jun 5, 2018 21:20    83.7 MB
9a1705b70  localhost/fortune:latest         Jun 19, 2018 19:21   127 MB




Zu den Themen Kubernetes, Docker und Cloud Architektur bieten wir sowohl Beratung, Entwicklungsunterstützung als auch passende Schulungen an:

Auch für Ihren individuellen Bedarf können wir Workshops und Schulungen anbieten. Sprechen Sie uns gerne an.

Feedback oder Fragen zu einem Artikel - per Twitter @triondevelop oder E-Mail freuen wir uns auf eine Kontaktaufnahme!

Los geht's!

Bitte teilen Sie uns mit, wie wir Sie am besten erreichen können.