7 Building Images With Buildah

This chapter describes how to use Buildah to create new images for use with Podman.

The Buildah utility is functionally similar to Podman in the way that it behaves, but maintains independence from Podman to facilitate the build of OCI compliant images. The primary difference between Buildah and Podman is in the way that the run command is handled. Because Buildah's purpose is to build images, the run command behaves the same as a RUN statement within a Containerfile, which is a configuration file that contains the required settings to automate the creation of a container image.

This difference makes it easy to separate image builds from production level container infrastructure, running in Podman, and to easily process existing Containerfile build instructions.

Use Buildah to pull images from existing registries and to change them to create new images with more specialized functionality. You can use Buildah with an existing Containerfile that works with Oracle Container Runtime for Docker to create an image, or alternately you can pull an image directly and change it within a container running within the Buildah environment.

Podman and Buildah use the same local image store, which means that you can start containers in Podman from images that you have built in Buildah. You can also use images that have been pulled locally by Podman as the base images which you use to build new images using Buildah. While local images are shared, the containers themselves run separately within Buildah and Podman. Podman is unable to access containers running within Buildah and Buildah is unable to access containers running within Podman. This is because the containers that run in Buildah are used precisely to run commands to build a new image.

For more information about the Containerfile format and build instructions see the containerfile(5) manual page.

For a complete listing of Buildah commands, run buildah help or view the buildah(1) manual page.

Creating Images From Containerfiles With Buildah

Buildah, which is designed to work directly with an existing Containerfile, processes the file to build an image using the 'build using dockerfile' or bud command. You can use any Containerfile that works with Oracle Container Runtime for Docker to build an image and the buildah bud command behaves similarly to the docker build command.

To build an image from a Containerfile, navigate to the directory where the file is located and type:

sudo buildah bud -t imagename .

Use the -f filename option if the file doesn't use the default Containerfile file name.

The built image is then tagged and added to the local image list. To confirm that the new image is available, type:

sudo buildah images

Note that because locally hosted images are shared between Buildah and Podman, the image is immediately available for use within Podman. However you might consider pushing the images to a registry where these images can become available to other systems where Podman is installed.

To verify an image by running it within a working container, type:

sudo buildah from imagename

The buildah from command creates a working container for any image. For more details, see Changing Images With Buildah.

Changing Images With Buildah

You change images by running them as working container instances within Buildah and issuing buildah run commands. These commands are the same as RUN statements in a Containerfile. After completing the changes to the working container, run the buildah commit to generate a new image based on the current status of the working container.

Setting Up Images and Working Containers

Buildah can pull images from a registry in the same way that you would pull an image by using Podman. For example, to pull the oraclelinux:7-slim image, you would type:

sudo buildah pull container-registry.oracle.com/os/oraclelinux:7-slim

Locally hosted images are shared between Buildah and Podman. To start a working container from any image within Buildah, use the buildah from command, for example:

sudo buildah from oraclelinux:7-slim
oraclelinux-working-container-1

You can combine a pull request with the buildah from command to start a container from an image hosted on a remote registry:

sudo buildah from container-registry.oracle.com/os/oraclelinux:7-slim

You can create and start a working container in any of the following ways:

  • Using a local image that you have pulled by using either Podman or Buildah
  • Using an image that was generated from a Containerfile
  • Using a remote image that you pulled directly from a remote registry.

To check which containers are available within Buildah, issue the following command:

sudo buildah containers

Making Changes to the Working Container

One of the key differences between Podman and Buildah is the handling of the run command. With Podman, this command emulates the equivalent Docker command and runs a process in a new container. With Buildah, the command behaves the same as a RUN statement from a Containerfile and affects the existing working container. You can use this command to run a series of commands against the working container to validate it, and to change it to a point where you're ready to store it as an image.

Use the buildah run command to run shell commands in the working container, such as installing packages and make system changes. The following command displays the Oracle Linux release in a specific container:

sudo buildah run oraclelinux-working-container-1 cat /etc/oracle-release
Oracle Linux Server release 8.2

To copy files to the working container, type:

sudo buildah copy oraclelinux-working-container-1 /path/to/yourscript /usr/local/bin

You can also make file changes inside the working container by mounting its root file system on the local host:

sudo buildah mount oraclelinux-working-container-1
/var/lib/containers/storage/overlay/5a595715c70a2d1a5582836d55722fbfc2ab9bf3/merged

The command returns the mount point where you can access the root file system for the container.

To change the file system to reflect directly within the container, type:

sudo touch /var/lib/containers/storage/overlay/5a595715c70a2d1a5582836d55722fbfc2ab9bf3/merged/testfile
sudo buildah run oraclelinux-working-container-1 ls /testfile
testfile

If you run the buildah mount command without any parameters, all mounts are displayed so that you can see which containers are mounted and the path to the mount point on the host system. Containers are listed by container ID, so you would need to match these to countainer names based on the information returned by the buildah containers command.

As a best practice, unmount container file systems when you're finished working on them by using the buildah unmount command. Note that this command isn't aware of container names, so you must use the command with the container ID, for example:

sudo buildah unmount 5617ebfbe265

Creating a New Image From the Working Container

Changes to the working container are temporary until they're committed to an image. Buildah enables you to commit an image locally for immediate use by Podman. However, Buildah also provides the facility to commit to a registry where you have write access. A range of options are available to help handle registry related access, such as authentication and certificate validation requirements. To find out about these options, see the buildah-commit(1) manual page.

To permanently store the changes to a working container as an image, use the buildah commit command. By running this command, you can start similar containers within the Podman environment. In the following example, the working container is committed locally and the --rm option is used to remove the working container from the Buildah environment at the same time:

sudo buildah commit --rm oraclelinux-working-container-1 new-image

To commit to a local registry, you would type:

sudo buildah commit --rm oraclelinux-working-container-1 docker://localhost:5000/new-image

Committing directly to a registry is the same as performing a local commit and then pushing it to a registry later by using the buildah push command.

You can also review the build image metadata with the buildah inspect command. The command output can help identify historical changes and other information about the image or working container, for example:

sudo buildah inspect --type image new-image

Removing a Working Container

The buildah rm command stops and removes a container from Buildah's container list.

sudo buildah rm oraclelinux-working-container-1

This command removes the working container and unmounts any mounts that might have been set up for it. After the container is removed, any changes that you made to the working container are lost and unretrievable unless you created an image of the working container before you removed it.

This command only removes the working container from the Buildah environment. Any containers running under Podman nor any existing images are unaffected. Because images are shared between Podman and Buildah, if you use the buildah rmi command to remove an image, the image is also removed for Podman.

Note:

As described in previous sections, using the --rm option with the buildah commit command enables you to both commit a working container and remove it from Buildah's container list at the same time. See Creating a New Image From the Working Container.

Pushing Images to a Registry

Buildah and Podman handle images interchangeably, so most of the commands that you run to work with images are replicated across these tools and perform the same operation. For example, the buildah push and podman push commands behave identically. You can use either of these commands to push an image that exists in local storage to a registry where you have write access.

To push a local image to a registry that uses the Docker Registry HTTP API V2, run the following command:

sudo buildah push imagename docker://registry.example.com/imagename:tag

Because Podman tries to maintain syntax compatibility with the Docker CLI, you can run this command by using the following syntax. The following sample command assumes that the local image is stored with its registry name and tag.:

sudo buildah push registry.example.com/imagename:tag

Registries are HTTP based resources that are typically protected by using TLS/SSL certificates and might require authentication. Several options that are related to how the command handles these requirements are available. For more information about these options, see the buildah-push(1) manual page.

Buildah and Podman are equally able to push images to other formats. Use this feature to create archive formats that you can share and reuse if you don't have access to a registry. For example, you can create a Docker compatible archive, similar to the results of running the docker save command in that environment. Type:

sudo buildah push imagename docker-archive:/path/to/archive-file:image:tag

Substitute docker-archive in the command with oci-archive to generate an archive that complies with the Open Container Initiative (OCI) specification.