Lightweight container tools: Buildah
1 June 2021
Glenn Janssens
Welcome back to our Container Tools blog series! In case you’re new, you can find our previous entry on podman here. Today, we’re going to explore Buildah, which works in tandem with the previous entry in our series.
Buildah
Buildah is provided in the container-tools along with podman and skopeo. In a nutshell, Buildah is used to build container images.There are a couple of different ways to do that depending on what you want to achieve:
- build from an existing image and optionally add your own changes to it-
- build from scratch (literally)
- build using Dockerfile (bud)
Building from an existing image
$ buildah from fedora Getting image source signatures Copying blob 8fde7942e775 done Copying config 79fd58dc76 done Writing manifest to image destination Storing signatures fedora-working-container
We now have a container named fedora-working-container, which is a container based on fedora we can customize.As you can see, the latest fedora image was automatically pulled to create it:
$ buildah images REPOSITORY TAG IMAGE ID CREATED SIZEregistry.fedoraproject.org/fedora latest 79fd58dc7611 3 weeks ago 181 MB
Lets add some customization to it.
$ buildah run fedora-working-container -- dnf -y install figlet Fedora 33 openh264 (From Cisco) - x86_64 1.4 kB/s | 2.5 kB 00:01 Fedora Modular 33 - x86_64 3.1 MB/s | 3.3 MB 00:01 Fedora Modular 33 - x86_64 - Updates 2.1 MB/s | 2.4 MB 00:01 Fedora 33 - x86_64 - Updates 9.1 MB/s | 13 MB 00:01 Fedora 33 - x86_64 20 MB/s | 72 MB 00:03 Dependencies resolved ....Installed: figlet-2.2.5-20.20151018gita565ae1.fc33.x86_64 Complete! $ buildah run fedora-working-container -- figlet FlowFactor
_____ _ _____ _ | ___| | _____ _| ___|_ _ ___| |_ ___ _ __ | |_ | |/ _ \ \ /\ / / |_ / _` |/ __| __/ _ \| '__| | _| | | (_) \ V V /| _| (_| | (__| || (_) | | |_| |_|\___/ \_/\_/ |_| \__,_|\___|\__\___/|_|
We can also set metadata or a specific command to run when the container starts.
$ buildah config --author FlowFactor
Metadata can be requested using buildah inspect:
$ buildah inspect fedora-working-container | grep author "author": "FlowFactor",
A run command can be set as such:
$ buildah config --cmd "/usr/bin/figlet FlowFactor" fedora-working-container
When you are happy with your changes, you can commit them to an image which is your end result.
$ buildah commit fedora-working-container flowfactor-blog-image Getting image source signatures Copying blob b4fa6ff1346d skipped: already exists Copying blob 4dbf9548b540 done Copying config 32cf87f303 done Writing manifest to image destination Storing signatures 32cf87f30319ca0573bd7b46cfacc9ccad9df37e4ed8bb16afbed00e22f9ad23
Once this is done, you can run a container from your image using podman:
$ podman run -t --rm flowfactor-blog-image _____ _ _____ _ | ___| | _____ _| ___|_ _ ___| |_ ___ _ __ | |_ | |/ _ \ \ /\ / / |_ / _` |/ __| __/ _ \| '__| | _| | | (_) \ V V /| _| (_| | (__| || (_) | | |_| |_|\___/ \_/\_/ |_| \__,_|\___|\__\___/|_|
Building from scratch
To get started, run
$ buildah from scratch working-container
Buildah detects the ‘scratch’ name and knows not to look for images and just provides with a container. This is definitely the most minimalistic way of creating an image, for when you create from scratch, you really have nothing:
$ buildah run working-container -- /bin/bash ERRO[0000] container_linux.go:367: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory error running container: error creating container for [/bin/bash]: : exit status 1
First we probably want to get our hands on a package manager to install something or bash to run some commands.We can do that by mounting the overlay filesystem of the newly created empty container:
$ buildah mount working-container /var/lib/containers/storage/overlay/88b9034c774b14874ec668fe0ed1a305831696eb5f3c59783d0a50b0c16ffe14/merged
The mounted filesystem is now also visible in the output of ‘df’:
$ df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 865M 0 865M 0% /dev tmpfs 881M 168K 881M 1% /dev/shm tmpfs 881M 25M 856M 3% /run tmpfs 881M 0 881M 0% /sys/fs/cgroup /dev/mapper/cs_vhost-root 70G 13G 58G 19% / /dev/mapper/cs_vhost-home 126G 1.1G 125G 1% /home /dev/sda2 1014M 229M 786M 23% /boot /dev/sda1 599M 6.9M 592M 2% /boot/efi tmpfs 391M 0 391M 0% /run/user/0 overlay 70G 13G 58G 19% /var/lib/containers/storage/overlay/88b9034c774b14874ec668fe0ed1a305831696eb5f3c59783d0a50b0c16ffe14/merged
Now, you can use the package manager of your host system to download the packages you onto your container overlay filesystem.
$ dnf install --installroot /var/lib/containers/storage/overlay/88b9034c774b14874ec668fe0ed1a305831696eb5f3c59783d0a50b0c16ffe14/merged --releasever 8 bash coreutils --setopt install_weak_deps=false -y $ buildah run working-container -- /bin/bash bash-4.4# cat /etc/*release CentOS Linux release 8.2.2004 (Core) NAME="CentOS Linux" VERSION="8 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="8" PLATFORM_ID="platform:el8" PRETTY_NAME="CentOS Linux 8 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:8" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-8" CENTOS_MANTISBT_PROJECT_VERSION="8" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="8" CentOS Linux release 8.2.2004 (Core) CentOS Linux release 8.2.2004 (Core)
As you can see, the host I used is running CentOS. At this point you can proceed like you would with an existing image.
Building using Dockerfile (BuD)
There are a couple of reasons to be working with Dockerfiles. You may have already have them from using Docker or simply prefer this format for templating or large configurations.
Simply create a file called Dockerfile (note the capital D) and paste your contents.
FROM fedora:latest RUN dnf -y update \ && dnf -y install figlet \ && dnf -y clean all # Run the httpd CMD ["/usr/bin/figlet", "FlowFactor"] $ buildah bud -t flowfactor-blog-fedora .
This will automatically search for a file called Dockerfile. Or, you could specify a different filename using the -f flag:
$ buildah bud -f Dockerfile -t flowfactor-blog-fedora . STEP 1: FROM fedora:latest STEP 2: RUN dnf -y update && dnf -y install figlet && dnf -y clean all ... 1/1 Installed: figlet-2.2.5-20.20151018gita565ae1.fc33.x86_64 Complete! STEP 3: CMD ["/usr/bin/figlet", "FlowFactor"] STEP 4: COMMIT flowfactor-blog-fedora Getting image source signatures Copying blob b4fa6ff1346d skipped: already exists Copying blob ea3e828df607 done Copying config 6f8cbd4dae done Writing manifest to image destination Storing signatures --> 6f8cbd4daed 6f8cbd4daedad56bd0866e6f448f33282740a1949a8af5f60b7f2e891717f041
We can now use podman to create a container from our newly created image and run it.
$ podman create --name ff-blog-fedora flowfactor-blog-fedora f724d0da0cd8e4e6ede8e637cbf72b443ecf0ff8841142cf99a9e5b97e622582 $ podman start ff-blog-fedora ff-blog-fedora $ podman logs ff-blog-fedora _____ _ _____ _ | ___| | _____ _| ___|_ _ ___| |_ ___ _ __ | |_ | |/ _ \ \ /\ / / |_ / _` |/ __| __/ _ \| '__| | _| | | (_) \ V V /| _| (_| | (__| || (_) | | |_| |_|\___/ \_/\_/ |_| \__,_|\___|\__\___/|_|
You can see what happened to the image and what’s set to run using:
$ podman history --notruncate flowfactor-blog-fedora 6f8cbd4daedad56bd0866e6f448f33282740a1949a8af5f60b7f2e891717f041 34 minutes ago /bin/sh -c #(nop) CMD ["/usr/bin/figlet", ... 108 MB 79fd58dc76113dac76a120f22cadecc3b2d1794b414f90ea368cf66096700053 34 minutes ago /bin/sh -c dnf -y update && dnf -y ins... 0 B
For me it did not show the complete commands, but formatting as json did.
$ podman history --format json flowfactor-blog-fedora [{"id":"6f8cbd4daedad56bd0866e6f448f33282740a1949a8af5f60b7f2e891717f041","created":"2020-11-19T23:00:29.468481227Z","CreatedBy":"/bin/sh -c #(nop) CMD [\"/usr/bin/figlet\", \"FlowFactor\"]","size":108463104,"Created":"2020-11-19T23:00:29Z"},{"id":"79fd58dc76113dac76a120f22cadecc3b2d1794b414f90ea368cf66096700053","created":"2020-11-20T00:00:28.16858609+01:00","CreatedBy":"/bin/sh -c dnf -y update \u0026\u0026 dnf -y install figlet \u0026\u0026 dnf -y clean all","size":0,"Created":"2020-11-20T00:00:28+01:00"},{"id":"\u003cmissing\u003e","created":"2020-10-27T07:49:11Z","size":181094400,"comment":"Created by Image Factory","Created":"2020-10-27T07:49:11Z"}]
Finally, the images that are built using buildah are completely OCI compliant and so can be consumed by podman, docker and other tools implementing the same standards. Using buildah push, you can push your image to any public or private OCI compliant registry. If the repository does not completely support OCI images, like dockerhub https://github.com/docker/hub-feedback/issues/1871, you can still use the –format flag to use docker’s format.
$ buildah bud --format docker -t flowfactor-blog-fedora . $ buildah push flowfactor-blog-fedora docker.io:flowfactor-blog-fedora:latest
Note that this last step may require you to log in to the container registry service.You can do this using ‘podman login’ or ‘buildah login’. This will create a token within your user namespace which can be reused by podman, buildah and skopeo.
Wondering what that last tool does exactly? Lucky for you we’re already working on the next entry. Stay tuned and be the first to read the next instalment in our series.
Sorry, the comment form is closed at this time.