As containerization continues to revolutionize the way we develop, package, and deploy software, the tools and workflows surrounding containers have evolved as well. One such tool that stands out in the container ecosystem is Buildah. It’s a powerful and flexible tool designed to help users build container images from scratch or from an existing base image, without requiring a full Docker daemon.
In this article, we’ll explore what Buildah is, why it’s important, how it works, and how you can use it in your container-based development pipelines.
What is Buildah?
Buildah is an open-source tool that provides a set of commands for building OCI (Open Container Initiative) and Docker container images. It was created to offer a more efficient, low-level alternative to Docker for building images. Unlike Docker, which typically requires a background daemon (dockerd), Buildah operates as a client-side tool and does not need a long-running process. This can make it more lightweight and secure for building container images, particularly in environments where a daemon is unnecessary or undesirable.
Buildah was developed by Red Hat as part of the container tools ecosystem, alongside other tools like Podman and Skopeo. It’s a part of the containers/image and containers/storage libraries, which provide flexibility and modularity for managing container images and local storage.
Key Features of Buildah
- Daemonless Operation: Unlike Docker, Buildah doesn’t require a running Docker daemon, which reduces resource overhead and improves security. This makes it a great choice for environments where minimal dependencies are required.
- OCI and Docker Image Support: Buildah supports building both OCI-compliant and Docker images, providing flexibility in image formats.
- Low-Level Control: Buildah allows you to manipulate images at a granular level, such as adding files, setting environment variables, and modifying image layers, providing greater control over the image-building process.
- Compatibility with Dockerfiles: While Buildah can operate independently of Docker, it supports the use of Dockerfiles to define image builds, making it compatible with existing workflows.
- Integration with Other Tools: Buildah can easily integrate with other container management tools like Podman, Kubernetes, and OpenShift, giving you a comprehensive suite of tools for container management.
- Lightweight and Secure: As a command-line tool, Buildah’s minimalistic approach to image building means it doesn’t require running a full container daemon or additional services, reducing the attack surface and simplifying the security model.
How Does Buildah Work?
At a high level, Buildah allows users to create container images in two main ways:
- Using a Dockerfile: Buildah can be used to build an image from a Dockerfile in much the same way as Docker would. It reads the Dockerfile, follows the instructions in sequence, and builds the image.
- Manually Building an Image: For more fine-grained control, Buildah allows you to manually create an image by specifying each step. You can add files, configure environment variables, run commands inside the container, and more.
Installing Buildah
# On Ubunutu
sudo apt insatall buildah
# On Archlinux
sudo pacman -S buildah
# On Fedora
sudo dnf install buildah
Buildah and Podman: How They Work Together
While Buildah is focused on building container images, Podman is concerned with running and managing those images as containers. The two tools are complementary and work well together in a seamless container workflow.
Build the Image with Buildah
List of all the images
To list of all the images that are currently built or pulled into the local buildah store (local image registry).
buildah images
Pull image and create container
buildah from <image-name>
# To force to pull from remote registry
buildah from --pull <image-name>
# pull alpine image
buildah from alpine
# other variations
buildah from --pull docker://myregistry.example.com/imagename
buildah from --name mycontainer dir:directoryname
buildah from oci-archive:filename
buildah from --name mycontainer docker-archive:filename
buildah from docker-daemon:imagename:imagetag
# if you execute the from command twice
## Then you will get 2 running containers
buildah from alpine
buildah from alpine
buildah ps
List running containers
To list of containers that are currently running or in the process of being built.This command behaves similarly to the ps command in Docker, showing the container ID, name, status, and other details about running or active containers
buildah ps
Lists all containers
ists all containers created with buildah, whether they are running or not.
buildah containers
# Lists all containers in JSON format
buildah containers --json
Runs a command inside the specified container
buildah run <container-name> <command>
# Run container with bindmount
# Here z = shared folder [host + container]
# U = if want to prevent other containers from reading or writing to the volume
buildah run -v /path/on/host:/path/in/container:z,U containerID sh
# To make bind mounted dir read only use ro flag
buildah run --volume /path/on/host:/path/in/container:ro,z containerID
# change network mode of container
#none, host ,private(default)
buildah run --net=<mode> containerID
# example
buildah run alpine-working-container apk update
buildah run alpine-working-container -- sh -c 'echo $PATH'
Copies a file from the host to the container
buildah copy <container-id> /path/to/file /container/path
# Examples
# sets the file permissions for the copied file inside the container.
buildah copy --chmod 660 containerID '/myapp/app.conf' '/myapp/app.conf'
buildah copy --chown myuser:mygroup containerID '/myapp/app.conf' '/myapp/app.conf'
# Muliple file/directory copy
buildah copy containerID 'passwd' 'certs.d' /etc
# git clone and copy with a single command
## When buildah sees a URL as the source, it will fetch the content from that URL and copy it into the container.
buildah copy containerID 'https://github.com/containers/buildah' '/tmp'
Copy file from container to host
buildah copy my-container /myapp/app.conf ./app.conf
# THis will copy to current dir
Access the shell of running container
buildah run --tty alpine-working-container sh
Rename container
buildah rename <containerName> <NewName>
Sets the entrypoint for the container
This is the first command to run when the container launches, much like a CMD or ENTRYPOINT directive in a Dockerfile.
buildah config --entrypoint <your/command> alpine-working-container
# example
# This sets the container's entrypoint to run Apache (httpd) with the -D FOREGROUND option, which keeps the server running in the foreground (a common configuration for containers running web servers).
buildah config --entrypoint "/usr/sbin/httpd -D FOREGROUND" alpine-working-container
# other versions
buildah config --entrypoint /entrypoint.sh containerID
buildah config --entrypoint '[ "/entrypoint.sh", "dev" ]' containerID
Sets the working directory for the container.
This command sets the working directory (like cd in a shell) inside the container.The working directory is where the commands will be executed within the container, making it the default directory when the container starts.
buildah config --workingdir <your/dir> alpine-working-container
# example
buildah config --workingdir /usr/local/myapp alpine-working-container
Remove/delete container
buildah rm <container-name>
# example
buildah rm alpine-working-container
Builds an image from a Dockerfile or container configuration
This command builds a container image based on a Dockerfile or other configuration files and tags it with the specified name.
buildah build -t <New custom image name>
# example
buildah build -t mycustomimage:1.0 .
Container inspection
The buildah inspect command provides detailed information about a container, including metadata, configuration, and state of the container.
buildah inspect <container-id>
Creating image based on container
The buildah commit command is used to create a new image from a container’s current state.It also specifies the output format for the new image, in this case, a Docker-compatible image format
buildah commit --format docker alpine-working-container <customImage:version>
# example
buildah commit --format docker alpine-working-container myapp:v1.0
# other versions
# rm Remove the working container and its contents after creating the image. Default leaves the container and its content in place.
# --format, -f [oci | docker]
# --disable-compression, -D
buildah commit --rm containerID newImageName
buildah commit --disable-compression containerID
buildah commit --disable-compression containerID newImageName
Container configuration
config : command is used to modify the configuration of a container, such as setting environment variables, changing the working directory, specifying entry points, setting exposed ports, and configuring volumes.
# This sets the author field in the image metadata. It's a useful field to specify who created the image. This information gets embedded into the image configuration and can be useful for tracking purposes.
buildah config --author='Jane Austen' --workingdir='/etc/mycontainers' containerID
# sets the entrypoint for the container.
buildah config --entrypoint /entrypoint.sh mycontainer
# This sets environment variables in the container.
buildah config --env foo=bar --env PATH=$PATH mycontainer
# Remove the env variable
buildah config --env foo- mycontainer
# This specifies that ports 1234 and 8080 should be exposed by the container. The container will be configured to accept traffic on these ports.
# This is similar to Docker's EXPOSE directive in a Dockerfile, but it doesn't automatically handle the mapping between the container and the host.
buildah config --port 1234 --port 8080 containerID
# This mounts a host directory (/usr/myvol) to a container directory (/container/path)
# in other words it is used for bind mounting
buildah config --volume /usr/myvol:/container/path containerID
# This command mounts a host directory to the container, but it does so without specifying a container path, meaning the mount path inside the container will mimic the host path.
buildah config --volume /usr/myvol mycontainer
Conclusion
Buildah is a powerful and flexible container image building tool that offers a lightweight, daemonless alternative to Docker. Its emphasis on security, low-level control, and flexibility makes it ideal for a range of use cases, including CI/CD pipelines, development workflows, and environments where Docker’s full daemon architecture is not desirable.