← Recipes

阅读中文版本

Speed Up Docker Builds with BuildKit Cache

Order layers from least to most volatile, mount caches for dependencies, and use a registry or GitHub Actions cache so CI rebuilds reuse work.

~35 mindockerbuildkitci

Task

Reduce Docker build time with BuildKit cache mounts and layer ordering.

When to use this

Every CI build reinstalls all dependencies from scratch because the cache is not persisted and layers are ordered so any change invalidates everything.

Prerequisites

  • Docker with BuildKit enabled
  • A cache backend for CI

Steps

1. Copy lockfiles first and install dependencies before copying source.

Expected output: Dependency layers cache across code changes.

2. Use cache mounts for package managers.

Expected output: Downloaded packages persist between builds.

3. Export and import the build cache in CI.

Expected output: Rebuilds reuse remote cache.

4. Verify a second build with no changes reuses cached layers.

DOCKER_BUILDKIT=1 docker build --cache-from type=registry,ref=app:cache .

Expected output: Cache is effective, not assumed.

Troubleshooting

Problem

Cache never hits

Solution

Ensure lockfiles are copied before source and the cache backend is correctly configured for export and import.

Problem

Image grows despite caching

Solution

Cache mounts reduce build time but do not shrink the final image; use multi-stage builds for size.

Limitations

  • BuildKit cache is not portable across all backends and can be invalidated by base image changes.
  • Aggressive caching can hide stale dependencies; rebuild cleanly before release.

Context

Reduce Docker build time with BuildKit cache mounts and layer ordering. Every CI build reinstalls all dependencies from scratch because the cache is not persisted and layers are ordered so any change invalidates everything.

Steps

  1. Copy lockfiles first and install dependencies before copying source. Expected: Dependency layers cache across code changes.
  2. Use cache mounts for package managers. Expected: Downloaded packages persist between builds.
  3. Export and import the build cache in CI. Expected: Rebuilds reuse remote cache.
  4. Verify a second build with no changes reuses cached layers. Expected: Cache is effective, not assumed.
# syntax=docker/dockerfile:1.6
FROM node:22-slim AS deps
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
    pnpm install --frozen-lockfile
FROM node:22-slim
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN pnpm build

Verify

  • Dependency layers cache across code changes.
  • Downloaded packages persist between builds.
  • Rebuilds reuse remote cache.
  • Cache is effective, not assumed.

Limits

  • BuildKit cache is not portable across all backends and can be invalidated by base image changes.
  • Aggressive caching can hide stale dependencies; rebuild cleanly before release.