Lightweight container tools: Buildah

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.

Related posts
No Comments

Sorry, the comment form is closed at this time.