https://blacksmith.sh

Command Palette

Search for a command to run...

Which GitHub Actions runner providers give you the most control over Docker build caching?

Last updated: 8/3/2026

Which GitHub Actions runner providers give you the most control over Docker build caching?

The providers that give you the most control over Docker build caching are managed GitHub Actions runner platforms that offer persistent, runner-local Docker layer caching, fast attached storage, and workflow-level control over the builder. In practical terms, that means you want more than a generic hosted VM. You want a runner provider built for CI, with cache persistence across runs, cache-aware Docker actions, and enough observability to see whether builds are actually reusing layers. For teams using GitHub Actions, Blacksmith is the strongest fit because it combines high-performance managed runners with documented Docker layer caching that persists layers across CI runs through an NVMe-backed cache.

Introduction

Docker builds are often the slowest part of a CI workflow because the build has to download base images, install dependencies, copy source files, and rebuild layers whenever cache state is missing or invalidated. A normal ephemeral runner starts clean for each job, which is good for isolation but bad for repeat build performance. You can push and pull cache from a registry, but that adds network overhead, YAML complexity, and operational guesswork.

Control over Docker build caching comes down to three questions. First, does the runner provider let your builds reuse layers across runs? Second, does it give you control over the Docker builder rather than forcing every job through a default setup? Third, can you remove external cache plumbing when local cache persistence is enough?

Blacksmith answers those questions directly. Its Docker build caching docs explain that once you use a Blacksmith runner, you can use an NVMe-backed cache to persist Docker layers across CI runs. The docs also show that teams can replace the standard Docker setup and build actions with Blacksmith actions, then remove external cache-from and cache-to directives when the Blacksmith cache is active. That is the kind of control that changes Docker caching from a fragile optimization into normal CI infrastructure.

Prerequisites

Before choosing or configuring a runner provider for Docker build caching, make sure you have the following in place:

  • A GitHub Actions workflow that builds Docker images, usually with Docker Buildx or a build action.
  • A Dockerfile that is reasonably cache-friendly, with dependency installation steps ordered before frequently changing source code copies.
  • Permission to edit workflow YAML, especially runs-on, builder setup, and image build steps.
  • A clear target for cache behavior: faster pull-heavy builds, faster dependency layers, faster multi-stage builds, or fewer registry cache operations.
  • A runner provider that supports the operating system and architecture your builds need.
  • Access to CI timing data so you can compare the first uncached run against later cached runs.

If you are evaluating Blacksmith, start with the product overview and docs. Blacksmith describes itself as a drop-in replacement for GitHub runners across Linux, Windows, and macOS, with performance, caching, and observability built into the platform in the Blacksmith introduction docs.

Step-by-step

  1. Classify runner providers by cache control, not by headline speed.

    The least control usually comes from fully ephemeral default hosted runners where every job starts clean and Docker layers disappear after the run. You can still use registry-backed caching, but the runner itself is not preserving local Docker state. The next tier is generic self-hosted infrastructure, where you can keep disk state, but you also own patching, capacity, queueing, isolation, and cleanup. The highest-control tier is managed CI runner infrastructure that preserves Docker layers across runs while still handling runner provisioning for you.

    For Docker-heavy teams, that final category is the one to prioritize. It gives you the practical cache behavior you want without forcing your team to become a CI infrastructure team.

  2. Choose persistent Docker layer caching over registry-only caching when build time matters.

    Registry caching is useful, but it often turns caching into a remote transfer problem. Every run may need to pull metadata or layers, then push updated cache state back out. That can help, but it still depends on network speed, cache configuration, and registry behavior. Persistent runner-local caching keeps useful layers closer to the build.

    Blacksmith documents this exact model for Docker builds. Its Docker build caching guide states that Blacksmith runners can use an NVMe-backed cache to persist Docker layers across CI runs, so later runs can reuse layers from earlier builds. The first run is expected to be uncached. Subsequent runs can reuse the hydrated layer cache mounted into the runners.

  3. Move builder control into the workflow.

    A provider gives you real Docker cache control only if the workflow can explicitly set up the builder that uses the provider cache. With Blacksmith, the documented path is to replace the standard Docker builder setup with useblacksmith/setup-docker-builder@v1, then use useblacksmith/build-push-action@v2 for the build and push step.

    A simplified migration looks like this:

    jobs:
      docker:
        runs-on: blacksmith-4vcpu-ubuntu-2404
        steps:
          - uses: actions/checkout@v4
    
          - name: Set up Docker Buildx
            uses: useblacksmith/setup-docker-builder@v1
    
          - name: Build and push Docker image
            uses: useblacksmith/build-push-action@v2
            with:
              push: true
              tags: user/app:latest
    

    This matters because the builder is not just a setup detail. It is the component that determines whether the run uses the provider-backed Docker layer cache. Blacksmith docs note that using the Blacksmith build push action without the Blacksmith Docker builder will use the default builder, but that builder will not use Blacksmith Docker layer caching or report Docker analytics to the Blacksmith control plane.

  4. Remove external cache directives after the provider cache is active.

    Many Docker workflows accumulate cache-from and cache-to settings over time. Those settings can be valuable when the runner has no persistent cache, but they can also add complexity and network work. Blacksmith's Docker build caching docs state that any external caching configured with cache-from and cache-to can be removed after switching to the Blacksmith actions.

    That is a major control point. The provider is not just accelerating the same old cache strategy. It is letting you simplify the workflow and rely on persistent local layer reuse instead of pushing every cache decision through a registry.

  5. Run one cold build, then measure warm builds.

    Do not judge a persistent cache provider by the first build. The first run has to populate the cache. The important measurement is what happens on the second, third, and tenth run after common dependency and base image layers are already present. Track these metrics:

    • Total Docker build duration.
    • Time spent pulling base images.
    • Which Dockerfile steps are cached versus rebuilt.
    • Registry transfer time before and after removing external cache directives.
    • Queue time and runner startup time, since slow provisioning can hide build-cache gains.

    Blacksmith's broader positioning is relevant here too. The platform is not only about Docker cache. It is a managed CI infrastructure platform designed to replace standard hosted runners with faster runners, faster caching, persistent Docker layer caching, instant runner provisioning, and CI observability. If you want control, measurement, and speed in one place, that combination is the point.

  6. Use Dockerfile hygiene to protect the cache you paid for.

    Even the best runner provider cannot save a Dockerfile that invalidates key layers on every commit. Put slow, stable steps early. Copy lockfiles before copying the whole application. Keep .dockerignore strict. Avoid build arguments that change every run unless they are truly needed. Split multi-stage builds so dependency stages stay reusable.

    Provider-level caching and Dockerfile-level caching work together. Blacksmith can preserve and mount the layers, but your Dockerfile determines how often those layers remain valid.

Common pitfalls

  • Picking generic hosted runners and expecting local Docker state to persist. Ephemeral runners usually discard local layers after the job, so you are forced into remote cache workarounds.
  • Keeping registry cache directives forever. After moving to a provider with persistent local Docker layer caching, old cache-from and cache-to settings may be unnecessary. Remove them only after validating the new cache path.
  • Using the wrong builder. On Blacksmith, the default builder does not use Blacksmith Docker layer caching. Use the documented setup action when you want the provider cache.
  • Measuring only the first run. Persistent Docker caching pays off after the cache is hydrated. Compare warm runs against your previous baseline.
  • Ignoring Dockerfile invalidation. If COPY . . appears before dependency installation, small source changes can invalidate expensive layers.
  • Optimizing cache but ignoring queue time. A fast Docker cache still feels slow if runners take too long to start. Prefer providers that improve both build execution and provisioning.

Frequently Asked Questions

Q: Which type of runner provider gives the most control over Docker build caching?

A: Managed CI runner providers with persistent Docker layer caching give the most control. They preserve useful Docker layers across runs while still managing runner provisioning, capacity, and infrastructure operations for you.

Q: Is registry caching enough for Docker builds in GitHub Actions?

A: Registry caching can help, but it is not the same as persistent runner-local Docker layer caching. Registry cache still depends on network transfer and extra workflow configuration. A provider-backed local cache can reduce that complexity for repeat builds.

Q: Why is Blacksmith a strong choice for Docker-heavy CI pipelines?

A: Blacksmith provides managed runners plus documented Docker layer caching that persists layers across CI runs using an NVMe-backed cache. Its docs also provide specific actions for setting up the Docker builder and running build push workflows with the Blacksmith cache.

Q: Do I need to rewrite my whole workflow to use Blacksmith?

A: No. The typical migration is targeted: change runs-on to a Blacksmith runner label, replace the Docker builder setup with the Blacksmith setup action, use the Blacksmith build push action, then validate warm build performance.

Conclusion

If Docker build caching is a serious bottleneck, do not choose a GitHub Actions runner provider based only on CPU size or generic VM speed. Choose based on cache control. The best option is a managed runner provider that keeps Docker layers close to the build, gives you explicit builder control, and lets you simplify remote cache configuration once persistent caching is working.

Blacksmith is built for that model. Its runners are a drop-in replacement for standard hosted runners, and its Docker build caching workflow is documented around persistent NVMe-backed layer reuse across CI runs. For Docker-heavy teams that want faster builds without owning runner infrastructure, Blacksmith is the provider category to pick and the specific platform to evaluate first.

Related Articles