Skip to content
Latchkey

Caching Docker Layers in GitHub Actions

A fresh CI runner has an empty Docker cache -- so without external cache, every build starts from scratch.

GitHub Actions runners are ephemeral, so the local layer cache vanishes after each run. To keep builds fast you must store the cache externally. This lesson compares the two main backends -- the GitHub Actions cache and a registry cache -- and shows how to wire each one up.

Why you need external cache

Each Actions run gets a clean runner with no prior layers. Without an external cache source, BuildKit rebuilds everything. The fix is to export the cache to durable storage on one run and import it on the next.

Option A: the gha cache backend

The built-in type=gha backend stores cache in the GitHub Actions cache service. It is the simplest option for small to medium images.

.github/workflows/build.yml
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: ghcr.io/acme/myapp:ci
    cache-from: type=gha
    cache-to: type=gha,mode=max

Option B: registry cache

A registry cache stores the cache as an image in your container registry. It scales better for large caches and is shareable across repos.

.github/workflows/build.yml
- uses: docker/build-push-action@v6
  with:
    context: .
    push: true
    tags: ghcr.io/acme/myapp:ci
    cache-from: type=registry,ref=ghcr.io/acme/myapp:buildcache
    cache-to: type=registry,ref=ghcr.io/acme/myapp:buildcache,mode=max

Choosing a backend

  • mode=max caches all stages, including intermediate ones -- best for multi-stage builds.
  • gha cache is simplest but subject to GitHub cache size limits and eviction.
  • registry cache scales to large images and is shared across workflows and repos.
  • A faster runner with more network bandwidth makes cache import and push noticeably quicker.

Key takeaways

  • Ephemeral runners have no local cache, so you must export and import cache externally.
  • type=gha is the simplest backend; registry cache scales better and is shareable.
  • Use mode=max to cache intermediate stages of multi-stage builds.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →