Chapter 19. Building container images with Buildah

Buildah facilitates building OCI container images that meet the OCI Runtime Specification. With Buildah, you can create a working container, either from scratch or using an image as a starting point. You can create an image either from a working container, using the instructions in a Containerfile, or by using a series of Buildah commands that emulate the commands found in a Containerfile.

19.1. The Buildah tool

Using Buildah is different from building images with the docker command in the following ways:

No Daemon
Buildah requires no container runtime.
Base image or scratch
You can build an image based on another container or start with an empty image (scratch).
Build tools are external

Buildah does not include build tools within the image itself. As a result, Buildah:

  • Reduces the size of built images.
  • Increases security of images by excluding software (for example gcc, make, and dnf) from the resulting image.
  • Allows to transport the images using fewer resources because of the reduced image size.
Compatibility
Buildah supports building container images with Dockerfiles allowing for an easy migration from Docker to Buildah.
Note

The default location Buildah uses for container storage is the same as the location the CRI-O container engine uses for storing local copies of images. As a result, the images pulled from a registry by either CRI-O or Buildah, or committed by the buildah command, are stored in the same directory structure. However, even though CRI-O and Buildah are currently able to share images, they cannot share containers.

19.2. Installing Buildah

Install the Buildah tool using the dnf command.

Procedure

  • Install the Buildah tool:

    # dnf -y install buildah

Verification

  • Display the help message:

    # buildah -h

19.3. Getting images with Buildah

Use the buildah from command to create a new working container from scratch or based on a specified image as a starting point.

Prerequisites

  • The container-tools meta-package is installed.

Procedure

  • Create a new working container based on the registry.redhat.io/ubi9/ubi image:

    # buildah from registry.access.redhat.com/ubi9/ubi
    Getting image source signatures
    Copying blob…
    Writing manifest to image destination
    Storing signatures
    ubi-working-container

Verification

  1. List all images in local storage:

    # buildah images
    REPOSITORY                                  TAG      IMAGE ID       CREATED       SIZE
    registry.access.redhat.com/ubi9/ubi         latest   272209ff0ae5   2 weeks ago   234 MB
  2. List the working containers and their base images:

    # buildah containers
    CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME
    01eab9588ae1     *     272209ff0ae5 registry.access.redhat.com/ub... ubi-working-container

Additional resources

  • buildah-from man page
  • buildah-images man page
  • buildah-containers man page

19.4. Building an image from a Containerfile with Buildah

Use the buildah bud command to build an image using instructions from a Containerfile.

Note

The buildah bud command uses a Containerfile if found in the context directory, if it is not found the buildah bud command uses a Dockerfile; otherwise any file can be specified with the --file option. The available commands that are usable inside a Containerfile and a Dockerfile are equivalent.

Prerequisites

  • The container-tools meta-package is installed.

Procedure

  1. Create a Containerfile:

    # cat Containerfile
    FROM registry.access.redhat.com/ubi9/ubi
    ADD myecho /usr/local/bin
    ENTRYPOINT "/usr/local/bin/myecho"
  2. Create a myecho script:

    # cat myecho
    echo "This container works!"
  3. Change the access permissions of myecho script:

    # chmod 755 myecho
  4. Build the myecho image using Containerfile in the current directory:

    # buildah bud -t myecho .
    STEP 1: FROM registry.access.redhat.com/ubi9/ubi
    STEP 2: ADD myecho /usr/local/bin
    STEP 3: ENTRYPOINT "/usr/local/bin/myecho"
    STEP 4: COMMIT myecho
    ...
    Storing signatures

Verification

  1. List all images:

    # buildah images
    REPOSITORY                                  TAG      IMAGE ID       CREATED              SIZE
    localhost/myecho                            latest   b28cd00741b3   About a minute ago   234 MB
  2. Run the myecho container based on the localhost/myecho image:

    # podman run --name=myecho localhost/myecho
    This container works!
  3. List all containers:

    # podman ps -a
    0d97517428d  localhost/myecho                                     12 seconds ago  Exited (0) 13 seconds ago          myecho
Note

You can use the podman history command to display the information about each layer used in the image.

Additional resources

  • buildah-bud man page

19.5. Creating images from scratch with Buildah

Instead of starting with a base image, you can create a new container that holds only a minimal amount of container metadata.

When creating an image from scratch container, consider:

  • You can copy the executable with no dependencies into the scratch image and make a few configuration settings to get a minimal container to work.
  • You must initialize an RPM database and add a release package in the container to use tools like dnf or rpm.
  • If you add a lot of packages, consider using the standard UBI or minimal UBI images instead of scratch images.

Prerequisites

  • The container-tools meta-package is installed.

Procedure

You can adds a web service httpd to a container and configures it to run.

  1. Create an empty container:

    # buildah from scratch
    working-container
  2. Mount the working-container container and save the mount point path to the scratchmnt variable:

    # scratchmnt=$(buildah mount working-container)
    
    
    # echo $scratchmnt
    /var/lib/containers/storage/overlay/be2eaecf9f74b6acfe4d0017dd5534fde06b2fa8de9ed875691f6ccc791c1836/merged
  3. Initialize an RPM database within the scratch image and add the redhat-release package:

    # dnf install -y --releasever=8 --installroot=$scratchmnt redhat-release
  4. Install the httpd service to the scratch directory:

    # dnf install -y --setopt=reposdir=/etc/yum.repos.d \
          --installroot=$scratchmnt \
          --setopt=cachedir=/var/cache/dnf httpd
  5. Create the $scratchmnt/var/www/html/index.html file:

    # mkdir -p $scratchmnt/var/www/html
    # echo "Your httpd container from scratch works!" > $scratchmnt/var/www/html/index.html
  6. Configure working-container to run the httpd daemon directly from the container:

    # buildah config --cmd "/usr/sbin/httpd -DFOREGROUND" working-container
    # buildah config --port 80/tcp working-container
    # buildah commit working-container localhost/myhttpd:latest

Verification

  1. List all images in local storage:

    # podman images
    REPOSITORY                                 TAG     IMAGE ID      CREATED         SIZE
    localhost/myhttpd                          latest  08da72792f60  2 minutes ago   121 MB
  2. Run the localhost/myhttpd image and configure port mappings between the container and the host system:

    # podman run -p 8080:80 -d --name myhttpd 08da72792f60
  3. Test the web server:

    # curl localhost:8080
    Your httpd container from scratch works!

Additional resources

  • buildah-config man page
  • buildah-commit man page

19.6. Removing images with Buildah

Use the buildah rmi command to remove locally stored container images. You can remove an image by its ID or name.

Prerequisites

  • The container-tools meta-package is installed.

Procedure

  1. List all images on your local system:

    # buildah images
    REPOSITORY                                  TAG      IMAGE ID       CREATED          SIZE
    localhost/johndoe/webserver                 latest   dc5fcc610313   46 minutes ago   263 MB
    docker.io/library/mynewecho                 latest   fa2091a7d8b6   17 hours ago     234 MB
    docker.io/library/myecho2                   latest   4547d2c3e436   6 days ago       234 MB
    localhost/myecho                            latest   b28cd00741b3   6 days ago       234 MB
    localhost/ubi-micro-httpd                   latest   c6a7678c4139   12 days ago      152 MB
    registry.access.redhat.com/ubi9/ubi         latest   272209ff0ae5   3 weeks ago      234 MB
  2. Remove the localhost/myecho image:

    # buildah rmi localhost/myecho
    • To remove multiple images:

      # buildah rmi docker.io/library/mynewecho docker.io/library/myecho2
    • To remove all images from your system:

      # buildah rmi -a
    • To remove images that have multiple names (tags) associated with them, add the -f option to remove them:

      # buildah rmi -f localhost/ubi-micro-httpd

Verification

  • Ensure that images were removed:

    # buildah images

Additional resources

  • buildah-rmi man page