Skip to content

BuildKit Guide

BuildKit is the next-generation build engine for Docker. It provides significant improvements in performance, storage management, feature set, and security compared to the legacy builder.

What is BuildKit?

BuildKit is a toolkit for converting source code into build artifacts efficiently. It is the default builder in Docker Desktop and Docker Engine 23.0+.

BuildKit vs Legacy Builder

FeatureLegacy BuilderBuildKit
Parallel execution❌ Sequential only✅ Concurrent stages
Build cacheBasic layer cacheAdvanced cache management
Build secrets❌ No native support--mount=type=secret
SSH forwarding❌ No native support--mount=type=ssh
Cache export/import❌ No✅ Multiple cache backends
Multi-platform builds❌ No✅ Cross-compilation
Custom outputs❌ Image only✅ Image, tar, local, OCI
Progress outputBasicRich, colored output
Build graph optimization❌ No✅ DAG-based execution
Garbage collection❌ No✅ Automatic

Enabling BuildKit

Docker Desktop

BuildKit is enabled by default in Docker Desktop. No configuration needed.

Docker Engine (Linux)

bash
# Option 1: Environment variable (per command)
DOCKER_BUILDKIT=1 docker build -t my-app .

# Option 2: Environment variable (session-wide)
export DOCKER_BUILDKIT=1

# Option 3: Daemon configuration (permanent)
# Add to /etc/docker/daemon.json:
{
  "features": {
    "buildkit": true
  }
}

# Restart Docker
sudo systemctl restart docker

# Verify BuildKit is enabled
docker buildx version

BuildKit Architecture

┌──────────────────────────────────────────────────────┐
│                    Docker Client                      │
│                (docker build / buildx)                │
└──────────────────────┬───────────────────────────────┘
                       │ gRPC

┌──────────────────────────────────────────────────────┐
│                     BuildKit                          │
│                                                      │
│  ┌──────────────────────────────────────────────┐   │
│  │              Frontend (LLB)                   │   │
│  │   Dockerfile → LLB (Low-Level Build)          │   │
│  └──────────────────────┬───────────────────────┘   │
│                         │                            │
│  ┌──────────────────────▼───────────────────────┐   │
│  │              Solver / Scheduler               │   │
│  │   Analyzes DAG → Parallel execution plan      │   │
│  └──────────────────────┬───────────────────────┘   │
│                         │                            │
│  ┌────────┐  ┌─────────▼──────┐  ┌──────────────┐  │
│  │ Cache  │  │   Workers      │  │  Exporters   │  │
│  │Manager │  │ (exec, OCI)    │  │ (image, tar) │  │
│  └────────┘  └────────────────┘  └──────────────┘  │
└──────────────────────────────────────────────────────┘

BuildKit Frontends

The frontend is responsible for parsing the build definition. The default frontend handles Dockerfiles.

Dockerfile Frontend

dockerfile
# syntax=docker/dockerfile:1

# The syntax directive tells BuildKit which frontend to use
# Always use the latest stable version for best features

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci
CMD ["node", "server.js"]

Syntax Versions

SyntaxFeatures
docker/dockerfile:1Latest stable features
docker/dockerfile:1.7Specific version
docker/dockerfile:labsExperimental features

BuildKit Mount Types

BuildKit introduces powerful --mount options for RUN instructions:

Cache Mounts

Cache mounts persist data between builds, dramatically speeding up package installations:

dockerfile
# syntax=docker/dockerfile:1

FROM node:20-alpine
WORKDIR /app

COPY package.json package-lock.json ./

# Cache npm packages between builds
RUN --mount=type=cache,target=/root/.npm \
    npm ci --only=production

COPY . .
CMD ["node", "server.js"]

Cache Mount Examples by Language

dockerfile
# Go modules cache
RUN --mount=type=cache,target=/go/pkg/mod \
    --mount=type=cache,target=/root/.cache/go-build \
    go build -o /app/server .

# Python pip cache
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

# Rust cargo cache
RUN --mount=type=cache,target=/usr/local/cargo/registry \
    --mount=type=cache,target=/app/target \
    cargo build --release

# Ruby bundler cache
RUN --mount=type=cache,target=/usr/local/bundle/cache \
    bundle install

# Maven cache (Java)
RUN --mount=type=cache,target=/root/.m2/repository \
    mvn package -DskipTests

# APT package cache
RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/var/lib/apt \
    apt-get update && apt-get install -y curl

Secret Mounts

Secret mounts make sensitive data available during build without persisting in image layers:

dockerfile
# syntax=docker/dockerfile:1

FROM node:20-alpine
WORKDIR /app

# Secret is available only during this RUN command
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci --only=production

# Secret for cloning private repos
RUN --mount=type=secret,id=github_token \
    GITHUB_TOKEN=$(cat /run/secrets/github_token) && \
    git clone https://${GITHUB_TOKEN}@github.com/private/repo.git
bash
# Pass secrets during build
docker build --secret id=npmrc,src=.npmrc \
             --secret id=github_token,src=./github-token.txt \
             -t my-app:1.0 .

SSH Mounts

SSH mounts forward the SSH agent for secure repository access:

dockerfile
# syntax=docker/dockerfile:1

FROM alpine:3.19
RUN apk add --no-cache git openssh-client

# Clone private repos using SSH agent
RUN --mount=type=ssh \
    mkdir -p /root/.ssh && \
    ssh-keyscan github.com >> /root/.ssh/known_hosts && \
    git clone [email protected]:private/repo.git /app
bash
# Build with SSH agent forwarding
eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa
docker build --ssh default -t my-app:1.0 .

Bind Mounts

Bind mounts make host files available during build without copying into the image:

dockerfile
# syntax=docker/dockerfile:1

FROM golang:1.22-alpine

WORKDIR /app

# Bind mount go.mod and go.sum for dependency download
RUN --mount=type=bind,source=go.mod,target=go.mod \
    --mount=type=bind,source=go.sum,target=go.sum \
    go mod download

# Bind mount source for building
RUN --mount=type=bind,target=. \
    go build -o /app/server .

tmpfs Mounts

tmpfs mounts create temporary filesystems in memory:

dockerfile
# syntax=docker/dockerfile:1

FROM ubuntu:22.04

# Use tmpfs for temporary build data
RUN --mount=type=tmpfs,target=/tmp \
    apt-get update && apt-get install -y build-essential && \
    make -j$(nproc) -C /src install

Mount Types Summary

Mount TypePurposePersists Between BuildsIn Final Image
cachePackage manager caches✅ Yes❌ No
secretSensitive data (tokens, keys)❌ No❌ No
sshSSH agent forwarding❌ No❌ No
bindHost files during buildN/A❌ No
tmpfsTemporary build data❌ No❌ No

Parallel Build Execution

BuildKit analyzes the build graph and executes independent operations in parallel:

dockerfile
# These stages run in parallel
FROM node:20-alpine AS frontend
WORKDIR /frontend
COPY frontend/ .
RUN npm ci && npm run build

FROM golang:1.22-alpine AS backend
WORKDIR /backend
COPY backend/ .
RUN go build -o server .

FROM python:3.12-slim AS ml-model
WORKDIR /ml
COPY ml/ .
RUN pip install -r requirements.txt

# Final stage waits for all parallel stages
FROM alpine:3.19
COPY --from=frontend /frontend/dist /app/public
COPY --from=backend /backend/server /app/server
COPY --from=ml-model /ml/model.pkl /app/model.pkl
CMD ["/app/server"]

BuildKit Builders

Builder Drivers

DriverDescriptionMulti-platformCache Export
dockerDefault Docker daemon builderLimited
docker-containerRuns BuildKit in a container
kubernetesRuns BuildKit in K8s pods
remoteConnect to remote BuildKit instance
bash
# Create a docker-container builder (recommended for advanced use)
docker buildx create --name mybuilder --driver docker-container --use

# Create a builder with specific configuration
docker buildx create \
  --name mybuilder \
  --driver docker-container \
  --driver-opt network=host \
  --buildkitd-flags '--oci-worker-gc-keepstorage 50000' \
  --use

# Bootstrap the builder
docker buildx inspect --bootstrap

# List builders
docker buildx ls

# Switch builders
docker buildx use mybuilder

# Remove a builder
docker buildx rm mybuilder

Garbage Collection

BuildKit automatically manages its cache with garbage collection:

toml
# /etc/buildkit/buildkitd.toml
[worker.oci]
  gc = true
  gckeepstorage = 50000  # 50 GB

  [[worker.oci.gcpolicy]]
    keepBytes = 10737418240    # 10 GB
    keepDuration = 604800      # 7 days (in seconds)
    filters = ["type==source.local", "type==exec.cachemount", "type==source.git.checkout"]

  [[worker.oci.gcpolicy]]
    all = true
    keepBytes = 53687091200    # 50 GB
bash
# Manually prune BuildKit cache
docker buildx prune

# Prune cache older than 24 hours
docker buildx prune --filter "until=24h"

# Prune all cache
docker buildx prune --all

Next Steps

基于 MIT 许可发布