Self-hosted service
moby/buildkit avatar
moby/buildkit

moby/buildkit: a standalone builder daemon for Dockerfiles and LLB

concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit

10,294 stars1,531 forksGoApache-2.0

At a glance

What is it?
BuildKit splits building into a buildkitd daemon and a buildctl client, with concurrent dependency resolution and cache export. This is what the repository documents, where it is thin, and when plain docker build is enough.
Who is it for?
Adopt standalone BuildKit if you need cache export to a registry, S3 or Azure Blob, a distributable worker topology, or execution without root privileges, and you are willing to run and operate a Linux daemon. Stay with the integrated builder if you only run docker build on a single machine: since Docker Engine 23.0 the README states that docker build uses Buildx and BuildKit by default, so the standalone daemon buys you nothing there.
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 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What BuildKit replaces, and who ends up running it

BuildKit is described in its README as "a toolkit for converting source code to build artifacts in an efficient, expressive and repeatable manner". That sentence hides the important part: it is not a CLI wrapper around a builder, it is the builder itself, shipped as a daemon plus a client. The README states that BuildKit is composed of the buildkitd daemon and the buildctl client, and that while buildctl is available for Linux, macOS and Windows, buildkitd is only available for Linux and Windows. If your build machines are not Linux or Windows, that constraint decides the question for you.

The audience is narrower than the project's adoption list suggests. BuildKit is used by Moby and Docker (through DOCKER_BUILDKIT=1 docker build), by Docker buildx, by Tekton Pipelines, by img, by Earthly earthfiles, by Dagger and by a long list of hosted build services. Most of those users never touch buildkitd directly, because the README notes that docker build uses Buildx and BuildKit by default since Docker Engine 23.0 and that you do not need to read the document unless you want the full-featured standalone version. The people who do read it are the ones who want the daemon on their own terms: a build service, a CI runner fleet, or a platform team that needs cache export to shared storage or a worker that runs without root.

The daemon, the worker backends, and the LLB layer underneath

The architecture visible in the repository is a client-server split. buildctl talks to buildkitd, and buildkitd does the work through a worker backend. The README states that the daemon supports two worker backends, OCI (runc) and containerd, and that the OCI worker is used by default. Switching to the containerd worker is a flag pair: --oci-worker=false --containerd-worker=true. That means the daemon's capabilities depend on which backend you choose, and the containerd path requires containerd to be installed, which the README lists as a prerequisite only "if you want to use containerd worker".

Below the frontend sits LLB, the low-level build definition. The repository has a client/llb package, examples/nested-llb and examples/dockerfile2llb, and the README's table of contents has an "Exploring LLB" entry. Dockerfile support is therefore not the core: it is one frontend that compiles a Dockerfile into LLB. The README's feature list says "Extendable frontend formats", and separately documents "Building a Dockerfile using external frontend", which is consistent with the frontend/ directory in the repository root. The practical consequence is that BuildKit can build things a Dockerfile cannot express, but only if you write LLB or adopt a frontend that does.

The feature list also names concurrent dependency resolution, efficient instruction caching, build cache import/export, nested build job invocations, distributable workers, multiple output formats, automatic garbage collection, a pluggable architecture and execution without root privileges. Those are the properties the standalone daemon exists to expose; the integrated Docker path exposes some of them and hides the configuration.

Installing BuildKit on Ubuntu and running a first build

The README points to the GitHub releases page for the latest binaries, available for Linux, macOS and Windows. It does not give a package repository or an apt command, so on Ubuntu you are installing a release binary rather than a distro package. For the daemon, the README lists runc or crun as required components, with containerd needed only for the containerd worker, and states that you need to run buildkitd as the root user on the host.

A minimal start of the daemon looks like this. The README shows the sudo form directly.

bash
$ sudo buildkitd

Once the daemon is listening, buildctl is the client. The README's quick start covers building a Dockerfile with buildctl and then choosing an output. A build that writes an image to a registry uses the registry output type; the README's Output section names Image/Registry, Local directory, Docker tarball, OCI tarball and containerd image store as the destinations. The exact flags for each destination are in that section rather than in the quick start, so read it before picking one.

The containerd worker is opt-in. If you want it, the README gives the switch as a flag pair on the daemon:

bash
$ sudo buildkitd --oci-worker=false --containerd-worker=true

If running as root is not acceptable, the README redirects to docs/rootless.md for running buildkitd as a non-root user. That file is the authority on the setup; the README itself only points at it. The same applies to Kubernetes: the README says to see examples/kubernetes for Kubernetes deployments, and there is an examples/kubernetes directory in the repository.

Cache export is the reason to run the daemon, and the least forgiving part

The cache section is where standalone BuildKit earns its keep. The README documents export targets for the build cache: inline (image and cache pushed together), registry (image and cache pushed separately), local directory, GitHub Actions cache marked experimental, S3 cache marked experimental, and Azure Blob Storage cache marked experimental. The go.mod file corroborates the storage backends by depending on the AWS SDK v2 S3 packages and the Azure azblob, azcore and azidentity modules, so the S3 and Azure paths are real code, not documentation stubs.

There is also a section on consistent hashing, with an examples/kube-consistent-hash directory in the repository, which matters when more than one daemon serves the same cache. Garbage collection is listed as a feature and has its own subsection, which tells you the cache is not meant to be kept forever; the README does not document a rollback procedure for a cache that has gone bad, and it does not document how to invalidate a single poisoned entry. That silence is the operational risk. If your builds depend on a shared remote cache, the failure mode is a build that silently reuses a layer you did not want, and the documented surface for fixing it is garbage collection, not surgical eviction.

The export targets marked experimental are another boundary. The README labels GitHub Actions, S3 and Azure Blob cache support as experimental, so a platform team standardising on one of them is standardising on an interface the project has not declared stable.

BuildKit versus Buildah and Kaniko, and versus Buildx

The comparison people actually search for is against Kaniko, and the honest difference is architectural. Kaniko is a single-purpose image builder designed to run inside a container without a daemon; the BuildKit README describes a daemon and client pair, with buildkitd running as root on the host by default, a rootless mode documented separately in docs/rootless.md, and a daemonless example under examples/buildctl-daemonless. So BuildKit can be used daemonless, but that is one documented example rather than the default posture. If your constraint is "no long-running process anywhere", the default BuildKit deployment does not match it.

Against Buildah the split is different again. Buildah is a command-line tool for building OCI images; BuildKit is a toolkit whose Dockerfile support is a frontend over LLB, with pluggable frontends and multiple output formats. BuildKit's advantage in that comparison is the cache export and the worker model, not the command surface. If you want a shell-driven image builder, BuildKit is the more elaborate answer.

The comparison against Buildx is not really a comparison, and the README says so: docker build uses Buildx and BuildKit by default since Docker Engine 23.0, and Buildx is listed among the projects that use BuildKit. Buildx is a client experience over BuildKit. Choosing "BuildKit instead of Buildx" usually means choosing the standalone daemon, which is exactly the case the README addresses with its note about not needing to read the document unless you want the full-featured standalone version.

Licence, upgrade cost, and what the repository tells you about maintenance

BuildKit is licensed under Apache-2.0, with the LICENSE file at the repository root. Apache-2.0 includes an express patent grant and requires preservation of notices; if you redistribute the binaries or embed the client/llb package in your own product, that is the clause to read with your own counsel rather than with an article. The repository also carries an AUTHORS file and a validate-authors Makefile target, which suggests contributor records are checked in CI.

The upgrade cost is dominated by the daemon, not the client. The repository's own Dockerfile pins the versions BuildKit is tested against, including RUNC_VERSION=v1.5.1, CONTAINERD_VERSION=v2.3.5 and ROOTLESSKIT_VERSION=v3.0.1, which tells you how many moving parts sit under the daemon. If you use the containerd worker, your containerd version is part of your compatibility surface. The go.mod file declares go 1.26.3, so building from source requires a recent Go toolchain; the README also has a "Build from source" section, and the Makefile exposes targets such as binaries, cross, images, frontends, install and test, all driven through buildx bake.

On maintenance, the facts are these: the repository is not archived, and the last push was on 2026-09-21. The most recent release listed is v0.33.0 from 2026-09-02, alongside dockerfile/1.27.0 and dockerfile/1.27.0-labs from the same day. That release cadence, with the frontend versioned separately from the daemon, is worth noting: upgrading the Dockerfile frontend and upgrading buildkitd are two decisions, and the labs channel exists as a separate tag.

Where BuildKit is the wrong tool

The clearest case against standalone BuildKit is a single developer machine or a small CI job that already has Docker. The README states that docker build uses Buildx and BuildKit by default since Docker Engine 23.0, so running your own buildkitd adds a daemon to operate, a socket to secure, and a root process to justify, in exchange for nothing you were not already getting. The README's own note says you do not need to read the document unless you want the full-featured standalone version, which is a fair summary of the trade.

The second case is any environment where buildkitd cannot run as root and you have not read docs/rootless.md. The README's default instruction is sudo buildkitd, and rootless is a separate document, not a flag. Treating rootless as a checkbox rather than a setup path is how teams end up with a daemon that starts and then fails to build.

The third case is a platform that needs a stable, non-experimental remote cache on GitHub Actions, S3 or Azure Blob. The README marks those three as experimental. If your build correctness depends on the remote cache, that label is the thing to weigh, not the feature list.

Editorial conclusion

Adopt standalone BuildKit if you need cache export to a registry, S3 or Azure Blob, a distributable worker topology, or execution without root privileges, and you are willing to run and operate a Linux daemon. Stay with the integrated builder if you only run docker build on a single machine: since Docker Engine 23.0 the README states that docker build uses Buildx and BuildKit by default, so the standalone daemon buys you nothing there. Before committing, verify the worker backend you intend to use (the OCI runc worker is the default, and the containerd worker requires containerd installed), whether your environment can run buildkitd as root or needs docs/rootless.md, and where your build cache will live, because the README documents export targets but not how to roll a cache back.

Frequently asked questions

What is BuildKit used for?

It converts source code into build artifacts, and the README describes it as a toolkit for doing so in an efficient, expressive and repeatable manner. In practice it is the builder behind docker build, Docker buildx, Tekton Pipelines, Dagger and several hosted build services.

Is BuildKit daemonless?

Not by default. The README states that BuildKit is composed of the buildkitd daemon and the buildctl client, and that buildkitd must be run as the root user on the host. A daemonless deployment is shown in the repository under examples/buildctl-daemonless.

Can I replace Kaniko with BuildKit?

BuildKit can run without a persistent daemon, since examples/buildctl-daemonless exists in the repository, but the documented default is a root-run buildkitd daemon plus a client. Kaniko's model is a single build container, so the substitution is an architectural change rather than a drop-in swap.

How do I install BuildKit on Ubuntu?

The README points to the GitHub releases page for the latest Linux, macOS and Windows binaries; it does not document an apt package. The daemon also requires runc or crun, and containerd if you want the containerd worker.

What is the BuildKit cache and how is it exported?

The README documents build cache import and export with several targets: inline (image and cache pushed together), registry (pushed separately), local directory, and GitHub Actions, S3 and Azure Blob caches, the last three marked experimental. Garbage collection is documented as a separate subsection.

What is moby/buildkit in Docker?

It is the BuildKit repository under the Moby organisation, and the README states that docker build uses Buildx and BuildKit by default since Docker Engine 23.0. The standalone daemon is only needed for the full-featured version.

Official sources

  1. License: Apache-2.0
  2. moby/buildkit 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/moby-buildkit.svg)](https://hysenlabs.com/projects/moby-buildkit)