Container Images ohne root bauen

Mit Podman und Buildah existieren Tools um OCI Images und Container zu erstellen, verwalten und betreiben - ganz ähnlich zum bekannten Docker. Die meiner Meinung nach größte Besonderheit: Die beiden funktionieren ohne Daemon, und auch ohne root-Rechte auf einem Linuxsystem.

Während podman meinen docker noch nicht ganz ersetzt (kein Unterstützung für/von docker-compose, da etwas anderer Fokus des Projekts) plane ich meine Build-Pipeline für Container-Images durch buildah zu ersetzen. Dadurch spare ich mir das Mounten des Docker-Sockets in den Container der Images bauen soll. :)

Ein erster Test Images im Container zu bauen lief wunderbar problemlos, ich schreibe hier auf was ich dafür getan habe.

Buildah im Container

Buildah kann fuse-overlayfs als Storage-Treiber nutzen, so dass auch die Verwaltung der Layer keine erweiterten Rechte braucht. Dazu muss allerdings das fuse-Device vom Host in den Container gemountet werden. Um die User-Namespaces nutzen zu können braucht es ausserdem mehr erlaubte Syscalls als in der Standardkonfiguration erlaubt.

Start des Containers also:

$ podman run -ti --rm --security-opt seccomp=unconfined --device /dev/fuse fedora bash

Im Container Buildah installieren:

# dnf install -y buildah

Und Fuse-Overlay konfigurieren:

# sed -i -e 's|#mount_program = "/usr/bin/fuse-overlayfs"|mount_program = "/usr/bin/fuse-overlayfs"|' /etc/containers/storage.conf

Als Beispiel baue ich Alpine mit zusätzlichem VIM:

# mkdir alpinewithvim
# cat > alpinewithvim/Dockerfile <<EOF
FROM alpine
RUN apk add --no-cache vim
EOF
# buildah bud --isolation chroot -t alpinewithvim alpinewithvim/

Was sauber durch lief:

# buildah images
REPOSITORY                 TAG      IMAGE ID       CREATED         SIZE
localhost/alpinewithvim    latest   0ca4abc241e0   6 seconds ago   36.6 MB
docker.io/library/alpine   latest   4d90542f0623   3 days ago      5.85 MB

Das gebaute Image lässt sich (genau wie bei Docker) in eine Registry schieben:

# buildah tag localhost/alpinewithvim reg.zknt.org/chris/alpinewithvim
# buildah push --creds chris reg.zknt.org/chris/alpinewithvim

Und damit kann das Image sonstwo geladen und als Container ausgeführt werden:

$ docker run --rm -ti reg.zknt.org/chris/alpinewithvim vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun  5 2019 08:37:43)
Included patches: 1-1365
Compiled by Alpine Linux
...

Buildah-Image

Als Image das automatisch ein Image baut und pusht sieht das ganze dann wie folgt aus.

Das Dockerfile:

FROM fedora
RUN dnf install -y buildah &&\
  sed -i -e 's|#mount_program = "/usr/bin/fuse-overlayfs"|mount_program = "/usr/bin/fuse-overlayfs"|' /etc/containers/storage.conf &&\
  mkdir /build
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT /entrypoint.sh

und das Entrypoint-Skript:

#!/bin/bash
buildah bud --isolation chroot -t ${BUILDAH_IMAGE_TAG} /build
buildah images
buildah push --creds "${BUILDAH_USER}:${BUILDAH_PASSWORD}" ${BUILDAH_IMAGE_TAG}

Mit diesem Image (als buildah getaggt) lassen sich jetzt (wie ich finde recht elegant) Images bauen und pushen:

podman run --rm -t --security-opt seccomp=unconfined --device /dev/fuse -v $(pwd)/alpinewithvim:/build -e BUILDAH_IMAGE_TAG=reg.zknt.org/chris/alpinewithvim -e BUILDAH_USER=chris -e BUILDAH_PASSWORD=hunter2 buildah

In ./alpinewithvim liegt das sinnfreie Dockerfile von weiter oben.

…jetzt das Ganze nur noch in Jenkins einbauen :)