logo

Cheatsheet - Buildah

Buildah is a command-line tool that facilitates building OCI (Open Container Initiative) compatible images. It allows for building images without a daemon, similar to how Docker CLI works but with a stronger focus on low-level container image manipulation, unprivileged operation, and direct integration with existing Linux tools.

Core Concepts

  • Image (Read-Only): A template from which containers are launched.
  • Container (Writable): A running instance of an image, or a temporary working space for building a new image. Buildah primarily uses containers as build stages.
  • Layer: Each instruction in a Dockerfile (or Buildah command) typically creates a new layer.
  • OCI Image/Container: Open Container Initiative standard for image and runtime specification.

Getting Started

1. Create a New Container (from scratch or an image)

  • Purpose: Start a new container to build upon.
  • Syntax:
    buildah from <image_name>
    buildah from scratch
    
  • Examples:
    buildah from ubuntu:22.04 # Start with an Ubuntu base image
    buildah from registry.access.redhat.com/ubi8/ubi # Use Red Hat UBI 8
    buildah from scratch # Start with an empty image (for static binaries)
    
  • Output: Returns the name of the new container (e.g., ubi-micro-working-container).
  • Tip: buildah from scratch is great for creating extremely minimal images, often used with COPY to add a static binary.

2. List Containers

  • Purpose: View active Buildah containers (which are essentially build environments).
  • Syntax:
    buildah containers
    
  • Example:
    buildah containers
    # CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME
    # c2f1a6b4a8e9    *        a24bb4014909 ubuntu:22.04                     ubuntu-working-container
    

Modifying Containers

1. Run Commands Inside the Container

  • Purpose: Execute commands within the build container. Similar to RUN in a Dockerfile.
  • Syntax:
    buildah run <container_name> <command>
    buildah run <container_name> -- <command_with_args>
    
  • Examples:
    buildah run ubuntu-working-container -- apt-get update
    buildah run ubuntu-working-container -- apt-get install -y nginx
    buildah run ubuntu-working-container -- bash -c "echo Hello from Buildah"
    
  • Tip: Use && to chain commands and reduce layers, just like in Dockerfiles.

2. Copy Files into the Container

  • Purpose: Copy files/directories from the host to the build container. Similar to COPY in a Dockerfile.
  • Syntax:
    buildah copy <container_name> <source_path> <destination_path_in_container>
    
  • Examples:
    buildah copy ubuntu-working-container ./app/index.html /var/www/html/
    buildah copy ubuntu-working-container requirements.txt /tmp/
    
  • Tip: Multiple source paths can be specified.

3. Add Files (with tar extraction/URL support)

  • Purpose: Similar to COPY, but also supports URL sources and extracts tar files. Similar to ADD in a Dockerfile.
  • Syntax:
    buildah add <container_name> <source_path_or_url> <destination_path_in_container>
    
  • Examples:
    buildah add ubuntu-working-container https://example.com/app.tar.gz /tmp/
    buildah add ubuntu-working-container my_app.tar /opt/
    

4. Set Environment Variables

  • Purpose: Define environment variables for the container and subsequent builds.
  • Syntax:
    buildah config --env <KEY>=<VALUE> <container_name>
    
  • Example:
    buildah config --env APP_ENV=production ubuntu-working-container
    

5. Set Working Directory

  • Purpose: Define the working directory for subsequent commands in the container.
  • Syntax:
    buildah config --workingdir <path> <container_name>
    
  • Example:
    buildah config --workingdir /app ubuntu-working-container
    

6. Expose Ports

  • Purpose: Declare which ports the container will listen on. (Documentation only, like EXPOSE in Dockerfile).
  • Syntax:
    buildah config --port <port>/<protocol> <container_name>
    
  • Example:
    buildah config --port 80/tcp --port 443/tcp ubuntu-working-container
    

7. Set Entrypoint

  • Purpose: Configure the default command to be executed when a container is run from the image.
  • Syntax:
    buildah config --entrypoint '["/usr/bin/nginx", "-g", "daemon off;"]' <container_name>
    buildah config --entrypoint '["/bin/sh", "-c", "echo Hello"]' <container_name>
    
  • Tip: Use JSON array format for exec form.

8. Set CMD (Default Command/Arguments)

  • Purpose: Provide default arguments to the ENTRYPOINT or a default command if no ENTRYPOINT is specified.
  • Syntax:
    buildah config --cmd '["-c", "/etc/nginx/nginx.conf"]' <container_name>
    buildah config --cmd '["/bin/bash"]' <container_name>
    
  • Tip: Use JSON array format for exec form.

9. Set User

  • Purpose: Set the user and/or group to run subsequent commands within the container.
  • Syntax:
    buildah config --user <user_name_or_uid>:<group_name_or_gid> <container_name>
    
  • Example:
    buildah config --user appuser:appgroup ubuntu-working-container
    

10. Set Labels

  • Purpose: Add metadata to the image.
  • Syntax:
    buildah config --label <KEY>=<VALUE> <container_name>
    
  • Example:
    buildah config --label maintainer="Your Name <[email protected]>" --label version="1.0" ubuntu-working-container
    

Committing and Exporting Images

1. Commit to an Image

  • Purpose: Save the changes in a build container as a new image.
  • Syntax:
    buildah commit <container_name> <image_name>[:<tag>]
    
  • Examples:
    buildah commit ubuntu-working-container my-nginx-image:latest
    buildah commit --format docker ubuntu-working-container my-nginx-image:latest # Specify Docker format
    buildah commit --rm ubuntu-working-container my-nginx-image:latest # Remove container after commit
    
  • Tip: Always commit your changes to create a new image.

2. List Images

  • Purpose: View locally stored OCI images.
  • Syntax:
    buildah images
    
  • Example:
    buildah images
    # REPOSITORY                          TAG       IMAGE ID       CREATED          SIZE
    # localhost/my-nginx-image            latest    2a1b3c4d5e6f   2 minutes ago    200 MB
    # docker.io/library/ubuntu            22.04     a24bb4014909   2 weeks ago      78 MB
    

3. Push Image to a Registry

  • Purpose: Upload a built image to a container registry (e.g., Docker Hub, Quay.io, GCR).
  • Syntax:
    buildah push <image_name> <registry_path>/<image_name>[:<tag>]
    
  • Examples:
    buildah push my-nginx-image:latest docker.io/myuser/my-nginx-image:latest
    buildah push my-nginx-image:latest quay.io/myorg/my-nginx-image:v1.0
    
  • Authentication: buildah login <registry_url> might be needed first.

4. Export Image to a Tarball

  • Purpose: Save an image to a tar archive for easy transfer.
  • Syntax:
    buildah push <image_name> docker-archive:<path_to_tarball>:<image_name>[:<tag>]
    
  • Example:
    buildah push my-nginx-image:latest docker-archive:my-nginx-image.tar:my-nginx-image:latest
    

Cleanup

1. Delete a Container

  • Purpose: Remove a Buildah build container.
  • Syntax:
    buildah rm <container_name_or_id>
    
  • Example:
    buildah rm ubuntu-working-container
    

2. Delete an Image

  • Purpose: Remove a local OCI image.
  • Syntax:
    buildah rmi <image_name_or_id>
    
  • Example:
    buildah rmi my-nginx-image:latest
    

3. Prune All Stopped Containers

  • Purpose: Remove all stopped build containers.
  • Syntax:
    buildah prune
    

Alternative Image Building (like docker build)

buildah bud (Build Using Dockerfile)

  • Purpose: Build an image from a Dockerfile. This command is more similar to docker build.
  • Syntax:
    buildah bud -t <image_name>[:<tag>] <path_to_build_context>
    buildah bud -f <path_to_Dockerfile> -t <image_name>[:<tag>] <path_to_build_context>
    
  • Examples:
    buildah bud -t myapp:latest . # Build from Dockerfile in current directory
    buildah bud -f mydockerfile -t myapp:v1.0 .
    
  • Tip: buildah bud is often a drop-in replacement for docker build for many simple Dockerfiles.

Miscellaneous

1. Mount a Container Filesystem

  • Purpose: Directly access and modify the container's filesystem from the host.
  • Syntax:
    buildah mount <container_name>
    
  • Example:
    MOUNT_POINT=$(buildah mount ubuntu-working-container)
    ls $MOUNT_POINT/
    # ... modify files directly ...
    buildah umount ubuntu-working-container # Always unmount!
    
  • Tip: This is a powerful feature for debugging or making manual changes that are hard with RUN or COPY. Remember to umount!

2. Unmount a Container Filesystem

  • Purpose: Unmount a previously mounted container filesystem.
  • Syntax:
    buildah umount <container_name>
    
  • Example:
    buildah umount ubuntu-working-container
    

3. Inspect Container or Image

  • Purpose: Display detailed low-level information about a container or image.
  • Syntax:
    buildah inspect <container_name_or_id>
    buildah inspect <image_name_or_id>
    
  • Example:
    buildah inspect my-nginx-image:latest
    

Buildah vs. Docker (CLI)

Feature Docker CLI (docker build) Buildah
Daemon Requires dockerd (daemon) to be running. Daemonless; interacts directly with host system for image layers.
Privileges Typically requires root or Docker group for dockerd. Can run entirely rootless (unprivileged).
Workflow Primarily uses Dockerfile with docker build. Allows granular, imperative steps (buildah from, run, commit). Also has buildah bud for Dockerfiles.
Mounting FS docker cp for file transfer; docker exec for commands. buildah mount allows direct host filesystem access to container layers.
Intermediate Containers Managed implicitly; not directly exposed. Build stages are explicit "containers" that can be manipulated and committed.
Use Case General-purpose container management, application deployment. Building OCI images, fine-grained image control, CI/CD, scripting.

Buildah vs Podman

Buildah is a specialized tool for building container images. While Podman can perform a build (by calling Buildah under the hood), Buildah is designed for granular, step-by-step image creation. It can replicate the instructions of a Dockerfile one at a time, allowing for more precise control over the image build process.

So docker, podman and buildah bud can all build based on a Dockerfile.