Self-hosted service
podman-container-tools/buildah avatar
podman-container-tools/buildah

Buildah: building OCI images without a daemon, and when that trade-off pays off

A tool that facilitates building OCI images.

9,047 stars934 forksGoApache-2.0

At a glance

What is it?
Buildah is a Go command line tool that builds OCI and Docker-format images from a working container or a Containerfile, without a daemon and without requiring root. It suits scripted, fine-grained image builds on Linux; it is not a container runtime and does not replace Podman or Docker for running workloads.
Who is it for?
Adopt Buildah if you build images on Linux from scripts or CI and want layer-level control without a daemon or root. Do not adopt it as a container runtime, and do not expect a supported path on macOS or Windows: the README points to Linux platforms and the project ships its own container images for the cases where you need it elsewhere.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Buildah solves: image construction as a scriptable primitive

Most image builders treat the build as one opaque step. You hand over a Dockerfile and get an image back, and anything you want to do between layers has to be expressed in Dockerfile syntax or bolted on with multi-stage tricks. Buildah takes the opposite position. Its commands replicate the instructions found in a Dockerfile, so `buildah from`, `buildah run`, `buildah copy`, `buildah config` and `buildah commit` map onto FROM, RUN, COPY, ENV/CMD/EXPOSE and the final commit. Because those are ordinary commands, a shell script can branch, loop or call out to another language between steps. The README's lighttpd example is exactly that: a bash script that creates a working container from `fedora`, runs `dnf update` and `dnf install` inside it, sets an annotation, a CMD and a port, then commits the result to an image name.

The audience follows from that design. Buildah is for people who build images on Linux and want the build expressed in something they already control, whether that is a Makefile, a CI job or a Go program that vendors the library. The README also states that images can be built in OCI image format or the traditional upstream Docker image format, so the output format is a choice rather than a fixed property of the tool.

Fork-exec, not a daemon: how the build actually runs

The README describes Buildah as following a simple fork-exec model, and says it does not run as a daemon. There is no long-lived process holding a socket that clients talk to. Each invocation starts, does its work against local storage, and exits. The same README notes that Buildah is based on a comprehensive API in Go that can be vendored into other tools, which is the second way to consume it: link the library rather than shell out.

Working containers are the central abstraction. `buildah from` creates one from scratch or from a base image, and the README lists mounting and unmounting a working container's root filesystem, using the updated contents as a filesystem layer, deleting a working container or image, and renaming a local container as first-class operations. That is a lower-level interface than a Dockerfile: you can mount the root filesystem, change it with ordinary tools, and commit. The README calls the goal a lower-level coreutils interface to building images.

The relationship with Podman is where people get confused, so it is worth stating plainly. Podman uses Buildah's Go API to build images from Dockerfiles, and can be installed independently of Buildah. The container concepts differ: Podman containers are meant to be long lived, while Buildah containers exist so content can be added back into an image. The README is explicit that `buildah run` emulates Dockerfile RUN while `podman run` emulates `docker run`, and that because of underlying storage differences you cannot see Podman containers from inside Buildah or the reverse.

Installing Buildah and a first scripted build

The README points to a separate installation document rather than embedding package commands, and it links to Buildah container images maintained in the containers/image_build repository. The install.md file in the repository root is the place to look for distribution-specific steps. Because install.md is not reproduced here, treat the commands below as the build itself rather than the installation.

The repository builds with make, and the Makefile sets PREFIX to /usr/local, BINDIR to $(PREFIX)/bin and BUILDAH to buildah, with build tags assembled from scripts under hack/ plus btrfs and libsubid detection. That means the binary is produced by the project's own build, not by a Go install command in the README.

bash
make
sudo make install

Once `buildah` is on PATH, the README's lighttpd example is the shortest complete workflow. It creates a working container from a base image, runs commands inside it, sets configuration, and commits it to a name.

bash
ctr1=$(buildah from "${1:-fedora}")
buildah run "$ctr1" -- dnf update -y
buildah run "$ctr1" -- dnf install -y lighttpd
buildah config --annotation "com.example.build.host=$(uname -n)" "$ctr1"
buildah config --cmd "/usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf" "$ctr1"
buildah config --port 80 "$ctr1"
buildah commit "$ctr1" "${2:-$USER/lighttpd}"

What you should see: the `buildah from` line prints the name of the new working container and assigns it to the shell variable, the two `buildah run` calls print the package manager's output, and the final `buildah commit` writes a new image under the name you passed. `buildah containers` lists working containers and their base images; `buildah images` lists images in local storage. If you already have a Containerfile, `buildah build` (documented as buildah-build) takes instructions from Containerfiles or Dockerfiles and is the Dockerfile-shaped entry point.

Where Buildah is the wrong tool

Buildah is not a container runtime. The README's own framing is that Buildah specializes in building images while Podman handles pulling, tagging, creating, running and maintaining containers. Buildah containers are created so content can be added back to an image, not to be long lived. If your requirement is to run a service, schedule workloads or keep a container alive, Buildah does not do that, and the storage separation means a Buildah working container is not visible to Podman anyway.

Platform is the second boundary. The README describes Buildah and Podman as available on most Linux platforms, and the related search data shows people asking about macOS and Windows. The README does not document a native macOS or Windows build. What it does offer is a link to Buildah container images, which is the route for using it from a non-Linux host. Anyone who needs a local, native builder on a developer laptop running macOS should check that container image path before assuming a direct install exists.

The third limitation is mechanical rather than conceptual. The Makefile assembles build tags from the host: an AppArmor tag script, a btrfs detection script, a libsubid tag script, a systemd tag script and a sqlite tag script, with SECURITYTAGS defaulting to seccomp plus the AppArmor result. A locally built binary therefore reflects what was present on the build machine. If you compile on a host without one of those pieces and then run the binary elsewhere, the feature is simply absent, and the failure will look like a missing capability rather than a configuration error.

Buildah against Docker, Kaniko and BuildKit

Docker's builder is the default comparison, and the difference is architectural. Docker builds through a daemon; Buildah follows a fork-exec model and does not run as a daemon. That matters most in CI, where a daemon means either a privileged service or a socket mounted into the job. Related searches pair Buildah with Kaniko, which takes a different route again: Kaniko is designed to build inside a container without a daemon, and it works from a Dockerfile. The practical distinction is that Kaniko's interface is the Dockerfile, while Buildah exposes the individual steps as commands that a script can interleave with anything else.

BuildKit sits on the other side of the line. It is a builder with its own execution model and caching, and the repository vendors `github.com/moby/buildkit` as a dependency, so the two are not mutually exclusive in the codebase. Choosing Buildah is choosing the imperative, command-per-step interface over a declarative build graph. Podman is the internal comparison: it uses Buildah's Go API for Dockerfile builds, so if you only ever build from a Containerfile and never need intermediate control, Podman already covers you and adds the run and manage side. Buildah is the right pick when the intermediate steps are the point.

Maintenance, releases and the licence

The repository is not archived, and the last push was on 2026-09-21. Recent releases include v1.45.1, v1.43.4 and v1.43.3, all published on 2026-09-15. The presence of parallel 1.45 and 1.43 lines is worth noting for anyone pinning versions: a fix can land on an older line, so checking the CHANGELOG.md in the repository is more reliable than assuming the highest version number is the only maintained one.

The go.mod file sets the module path to go.podman.io/buildah and declares go 1.26.3, with a comment warning that the go and toolchain versions must match exactly to prevent unwanted auto-updates. That is a real upgrade constraint: building from source requires a Go toolchain at that version, and the dependency list is long, pulling in containerd, containers/image and storage, opencontainers runtime and image specs, moby/buildkit and others. Vendoring the library into your own Go program inherits that dependency surface. Buildah also ships a developmentplan.md and a ROADMAP.md, which is where to look for direction rather than inferring it from commit volume.

The licence is Apache-2.0, stated in the repository's LICENSE file. Apache-2.0 is a permissive licence with an explicit patent grant and requires that notices and the licence text be preserved in redistributions. It is compatible with many proprietary uses, but the details depend on how you redistribute, and that is a question for your own legal review rather than something this article can settle.

Editorial conclusion

Adopt Buildah if you build images on Linux from scripts or CI and want layer-level control without a daemon or root. Do not adopt it as a container runtime, and do not expect a supported path on macOS or Windows: the README points to Linux platforms and the project ships its own container images for the cases where you need it elsewhere. Before committing, verify that your storage driver works with the tags your build selects, and read install.md for your distribution rather than guessing at a package name.

Frequently asked questions

What is Buildah used for?

Buildah builds OCI and Docker-format container images. Its commands replicate the instructions in a Dockerfile, so it can build from a Containerfile or from individual commands run against a working container, and it can do so without root privileges.

Why use Buildah instead of Docker?

The README describes Buildah as following a fork-exec model with no daemon, while Docker builds through a daemon. Buildah also exposes the build as separate commands, which lets scripts interleave other tooling between steps instead of expressing everything in Dockerfile syntax.

Is Buildah daemonless?

Yes. The README states that Buildah follows a simple fork-exec model and does not run as a daemon, and that it is based on a Go API that can be vendored into other tools.

Is Buildah free to use?

The repository is licensed under Apache-2.0, which permits commercial and private use. Redistributions need to preserve the licence and notices.

How do I install Buildah on Ubuntu?

The README links to a separate installation notes file, install.md, in the repository rather than listing distribution commands. That file is the place to check for Ubuntu, and the README also links to Buildah container images for cases where a package is not the route.

What is buildah bud?

The command table lists buildah-build as the command that builds an image using instructions from Containerfiles or Dockerfiles. The older bud spelling refers to that Dockerfile-driven entry point, as opposed to assembling an image with buildah from, run, config and commit.

Official sources

  1. License: Apache-2.0
  2. podman-container-tools/buildah on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/podman-container-tools-buildah.svg)](https://hysenlabs.com/projects/podman-container-tools-buildah)