BuildKit and Buildx

BuildKit is Docker’s modern build backend. It improves build speed, cache behavior, Dockerfile features, and multi-platform output. Docker Engine uses BuildKit by default in current releases, and docker buildx is the CLI front end for advanced builds.

Check the local builder first.

1docker buildx version
2docker buildx ls

The default builder is enough for many local builds. For multi-platform builds, shared registry cache, or isolated CI builders, create a named builder that uses the docker-container driver.

1docker buildx create --name book-builder --driver docker-container --use
2docker buildx inspect --bootstrap

Dockerfile syntax

Start Dockerfiles that use newer BuildKit features with the syntax directive.

1# syntax=docker/dockerfile:1
2FROM python:3-slim

The directive lets Docker use the current stable Dockerfile frontend even when the builder host is not upgraded at the same pace as the project.

Cache mounts

Cache mounts keep dependency caches outside the final image while still reusing them across builds. This pattern is useful for package managers such as pip, npm, apt, maven and gradle.

 1# syntax=docker/dockerfile:1
 2FROM python:3-slim
 3
 4WORKDIR /app
 5COPY requirements.txt .
 6RUN --mount=type=cache,target=/root/.cache/pip \
 7    pip install --no-cache-dir -r requirements.txt
 8
 9COPY . .
10CMD ["python", "app.py"]

The cache directory is available while the RUN instruction executes. It is not copied into the image layer.

Build secrets

Do not pass tokens through ARG or ENV. They can leak through image history or build logs. Use BuildKit secrets so credentials are mounted only for the instruction that needs them.

1export PIP_TOKEN="..."
2docker buildx build \
3    --secret id=pip_token,env=PIP_TOKEN \
4    -t example/app:dev .

The Dockerfile reads the secret from the temporary mount.

1# syntax=docker/dockerfile:1
2RUN --mount=type=secret,id=pip_token \
3    PIP_TOKEN="$(cat /run/secrets/pip_token)" && \
4    pip config set global.extra-index-url "https://token:${PIP_TOKEN}@packages.example.com/simple"

Registry cache

CI runners are often ephemeral. Registry-backed cache lets each new runner reuse layers from previous builds.

1docker buildx build \
2    --cache-from type=registry,ref=registry.example.com/team/app:buildcache \
3    --cache-to type=registry,ref=registry.example.com/team/app:buildcache,mode=max \
4    -t registry.example.com/team/app:${GIT_SHA} \
5    --push .

Use a separate cache tag so application tags and build-cache metadata have different lifecycles.

Build output

Buildx can load an image into the local Docker image store, push it to a registry, or write files to disk.

1# Local single-platform development image
2docker buildx build --load -t example/app:dev .
3
4# Registry image for deployment
5docker buildx build --platform linux/amd64 -t registry.example.com/team/app:prod --push .

Keep ordinary docker build for quick local work when it is enough. Move to docker buildx build when the build needs cache export, secrets, attestations, or multi-platform output.

References