← Back to DevBytes

Docker BuildKit: Complete Configuration Guide

Docker BuildKit: Complete Configuration Guide

What is Docker BuildKit?

BuildKit is a next-generation build engine shipped with Docker, designed to replace the legacy builder. It introduces a highly parallelized, cache-efficient, and extensible architecture for building container images. Originally released as an experimental feature, BuildKit became the default builder in Docker 23.0 and later, and is fully integrated into the Docker CLI and Docker Compose.

Under the hood, BuildKit uses a concurrent execution model with a directed acyclic graph (DAG) solver. It can parallelize independent build steps, skip unnecessary stages when cache is available, and support advanced features like secrets management, SSH agent forwarding, and multi-stage build caching across different environments. The engine itself can run either as a built‑in component of the Docker daemon or as a standalone buildkitd service, enabling remote builds and integration with CI/CD systems.

Why BuildKit Matters

Moving from the classic builder to BuildKit brings substantial benefits:

Enabling and Configuring BuildKit

BuildKit is now the default builder in modern Docker installations. You can verify which builder is active and control its configuration via environment variables, daemon‑level settings, and CLI flags. The following sections cover all common configuration scenarios.

1. Enable BuildKit via Environment Variable

The simplest way to force BuildKit for a specific session or script is to set the DOCKER_BUILDKIT environment variable. This works with the docker build command and overrides any default.

# Enable BuildKit for the current shell session
export DOCKER_BUILDKIT=1

# Use it in a single command
DOCKER_BUILDKIT=1 docker build -t myapp:latest .

# Disable it (legacy builder) by setting to 0
DOCKER_BUILDKIT=0 docker build -t myapp:legacy .

2. Daemon‑level Configuration (dockerd)

For persistent, system‑wide BuildKit activation, edit the Docker daemon configuration file, usually located at /etc/docker/daemon.json. Add the "buildkit" key to the "features" section (or "builder" in older versions). After modifying, restart the Docker daemon.

{
  "features": {
    "buildkit": true
  }
}

On newer Docker versions (23+), BuildKit is the default, so this entry may be redundant, but it ensures the feature is explicitly enabled. You can also disable it by setting "buildkit": false.

3. Using the Docker Buildx Client (Recommended)

Docker Buildx is a CLI plugin that exposes advanced BuildKit capabilities, such as creating multi‑platform images, exporting cache, and managing builder instances. Buildx is bundled with Docker Desktop and most package installations. To use it, simply invoke docker buildx build instead of docker build. It automatically uses BuildKit under the hood and provides richer options.

# Create a new BuildKit‑backed builder instance
docker buildx create --name mybuilder --use

# Inspect and verify the builder
docker buildx inspect --bootstrap

# Build with Buildx, targeting multiple platforms
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:multi --push .

4. Standalone BuildKit Daemon (buildkitd)

For environments where you want to decouple the build engine from the Docker runtime (e.g., a CI cluster or a dedicated build server), you can run the BuildKit daemon as a standalone service. This requires the buildkitd binary, usually available from the moby/buildkit repository.

# Run buildkitd with default options (listens on unix socket and TCP)
buildkitd --addr unix:///run/buildkit/buildkitd.sock --addr tcp://0.0.0.0:1234

Then configure the Buildx client to connect to this remote builder:

docker buildx create --name remote-builder --driver remote \
  --addr tcp://buildkit-host:1234 --use

BuildKit Configuration Options

BuildKit can be tuned via a TOML‑based configuration file when running the standalone buildkitd daemon. The config file is typically located at /etc/buildkit/buildkitd.toml or passed via the --config flag. Docker’s integrated BuildKit (through dockerd) respects a subset of these options through the daemon.json, but for advanced tuning the standalone daemon is preferred.

Core Configuration Sections

A typical buildkitd.toml looks like this:

# /etc/buildkit/buildkitd.toml
debug = false

[worker]
  [worker.oci]
    enabled = true
    # maximum number of parallel build steps
    max-parallelism = 4

  [worker.containerd]
    enabled = false

[registry]
  [registry."docker.io"]
    mirrors = ["mirror.company.com"]
    plainHTTP = false

[dns]
  # DNS servers used during build
  nameservers = ["8.8.8.8", "1.1.1.1"]
  options = ["edns0"]

Key areas you can control:

Advanced Dockerfile Features Enabled by BuildKit

With BuildKit, you unlock a powerful set of Dockerfile instructions. These features are not available in the legacy builder. Below are some of the most impactful ones.

Secret Mounts (RUN --mount=type=secret)

Mount secrets such as private keys, tokens, or environment‑specific files without baking them into the final image. Secrets are available only during the execution of the current RUN instruction.

# Dockerfile
FROM alpine

# Secret file mounted at /run/secrets/mykey
RUN --mount=type=secret,id=mysecret,dst=/run/secrets/mykey \
    cat /run/secrets/mykey && \
    # do something with the secret, then it disappears

Supply the secret at build time:

# Using a file as secret
docker build --secret id=mysecret,src=./secret.txt -t myapp .

# Using environment variable via heredoc
docker build --secret id=mysecret,src=/dev/stdin -t myapp <<< "$MY_TOKEN"

SSH Agent Forwarding (RUN --mount=type=ssh)

Forward your SSH agent socket into the build, allowing git clone from private repositories or other SSH‑based operations without embedding keys.

# Dockerfile
FROM golang:1.21

# Use SSH to clone private Go modules
RUN --mount=type=ssh \
    mkdir -p /root/.ssh && \
    ssh-keyscan github.com >> /root/.ssh/known_hosts && \
    go build -o /app ./...

Build with SSH agent forwarding:

docker build --ssh default -t myapp .

Cache Mounts (RUN --mount=type=cache)

Persist directories across builds (e.g., package manager caches) to dramatically speed up subsequent runs. The cache is stored outside the image layers and shared between builds.

# Dockerfile
FROM node:18

# Cache npm dependencies across builds
RUN --mount=type=cache,target=/root/.npm \
    npm install && \
    npm run build

Heredoc Syntax for Multi‑line Commands

BuildKit supports heredocs, letting you write complex scripts directly in RUN or COPY instructions without a separate script file.

# Dockerfile (heredoc example)
FROM python:3.11

RUN <

Best Practices for BuildKit Configuration

To get the most out of BuildKit while maintaining security and performance, follow these guidelines:

  • Use Buildx for all buildsdocker buildx build gives you immediate access to advanced features, multi‑platform builds, and better output options (e.g., --output=type=tar).
  • Leverage cache mounts extensively – Mount package manager caches (~/.cache/pip, /root/.npm, /go/pkg/mod) to reduce download times and speed up CI pipelines.
  • Never copy secrets into images – Always use --secret mounts for credentials, API keys, and certificates. Combine with multi‑stage builds to keep sensitive data out of final layers.
  • Enable remote builders for CI/CD – Run buildkitd on dedicated hardware and connect via Buildx to share a common cache and offload builds from ephemeral CI runners.
  • Tune parallelism – On multi‑core machines, set max-parallelism to a value slightly lower than the number of CPU cores to avoid resource contention. Monitor and adjust based on build times.
  • Use a local registry mirror – Configure [registry] mirrors for docker.io and internal registries to reduce pull latency and avoid rate limits.
  • Enable BuildKit in Docker Compose – Set COMPOSE_DOCKER_CLI_BUILD=1 and DOCKER_BUILDKIT=1 in your environment to force Compose to use BuildKit for all services, unlocking cache mounts and secrets in compose builds.
  • Clean up builder instances – Use docker buildx prune regularly to reclaim disk space from build caches, especially on CI servers.

Troubleshooting Common Issues

When BuildKit behaves unexpectedly, here are quick checks:

  • Verify the active builder with docker buildx inspect or docker build --progress=plain --no-cache . and look for BuildKit version in the output.
  • If secrets are not available, ensure the --secret flag is passed and the id matches the Dockerfile mount declaration.
  • For SSH forwarding failures, confirm the SSH agent is running (eval $(ssh-agent)) and the key is added (ssh-add -l).
  • When using a standalone buildkitd, check connectivity with buildctl debug workers --addr tcp://host:1234.

Conclusion

Docker BuildKit is no longer an experimental extra – it is the standard build engine for modern container workflows. By understanding its configuration surface, from the simple environment variable to the standalone daemon TOML file, you unlock faster, safer, and more flexible image builds. Adopting Buildx as your primary build interface, integrating secret mounts and cache mounts into your Dockerfiles, and tuning the build environment to your infrastructure will pay immediate dividends in build performance and security. Whether you are developing locally, running CI/CD pipelines, or maintaining a fleet of production images, BuildKit provides the foundation for a truly efficient build system.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles