Skip to content

Docker builds that remember their layers.

A Docker layer cache that survives between jobs, switched on with one line, at $0.50 per GB-month, metered by what it stores.

Connect GitHub

Card required. 3,000 minutes a month at 2 vCPU are included.

One line

.github/workflows/ci.yml
steps: - uses: actions/checkout@v4 + - uses: runners-io/setup-docker-builder@v1 - run: docker build -t app .

The step points BuildKit at a layer cache beside the runners, reachable from a job and from nowhere else. A layer that has not changed is not rebuilt and not uploaded again. If the cache cannot be reached the build runs without it and is only slower. The full description is in the documentation.

One build, measured

We built result/Dockerfile from dockersamples/example-voting-app (Apache-2.0, commit 63e9150) with a plain docker build after the one added step. Each build was a separate job on a fresh virtual machine. The first of each series found an empty cache; the others found the layers it left.

BuildSeconds, each of 9 buildsMedian
Cold: empty cache19.8, 25.2, 47.925.2 s
Warm: layers from the cache3.6, 3.2, 3.2, 4.6, 12.8, 3.03.4 s

Measured 7 November 2026 on a runnersio-2vcpu-ubuntu-2404 runner, in a test repository of ours, each build on whichever runner was free, and none was left out, so the spread is real. One Dockerfile is one Dockerfile: a build that spends its time elsewhere gains less, and these numbers are the wall time of the docker build command, including pulling the base image.

The three steps that matter, so you can repeat it. This is the workflow we ran with its timing lines taken out; the first build under a new cache name is the cold one:

.github/workflows/ci.yml
steps: - uses: actions/checkout@v4 with: repository: dockersamples/example-voting-app ref: 63e9150ca17af4ed05880d4245e486481f73fcb4 - id: builder uses: runners-io/setup-docker-builder@v1 with: key: measure-pick-a-new-name-for-a-cold-build - name: Build, timed working-directory: result run: time docker build --progress=plain -t measure-result .

The ones worth asking first

How do I turn the Docker layer cache on?

Add one step before your build: uses: runners-io/setup-docker-builder@v1. Every docker build, docker buildx build and docker/build-push-action step after it in the same job reads its layers from the cache and writes new ones back. Nothing else in the workflow changes.

What does the layer cache cost?

$0.50, metered by what it stores. A layer the cache deletes stops counting.

How long are layers kept?

A cache tag that no build has read or written for seven days is deleted, then the layers no tag of yours points to. If a push would take your organisation's layer cache past 10 GiB, we first delete layers nothing points to, then that repository's cache tags that no build has used for the longest (never one used in the last two days) until the push fits. We never delete another repository's tags to make room. If nothing is old enough, new layers are not stored and the build carries on without them.

Is one repository's cache visible to another?

No. The cache belongs to one repository of one GitHub account, and a build reads only the layers its own branch and the default branch wrote.

What does it not do?

It caches layers, not your build context or test fixtures. It is not offered on Windows jobs, and it does not make a built image available to a later job as an image. If your slow step is downloading dependencies rather than building layers, the Actions cache is the mechanism that helps.

Before you connect

Is my code safe on someone else's runner?

Each job gets its own virtual machine, starting fresh and shared with no other job. Nothing a job leaves on its machine can be seen by another job.

What do you get from my GitHub account?

Access to the repositories you choose, and nothing else. We read their workflow files and job logs, register a runner for each job, and open the pull request that moves them across. Your secrets, environments and branch protection stay on GitHub, and every permission is listed, with what it is for, in the docs under Connect your account.

What if I do not want to depend on a vendor?

The one change a workflow needs is the runs-on label. Your actions, secrets and triggers are untouched, so there is nothing of ours to untangle.

How do I leave?

Change the label back and the job runs on GitHub again. We delete build output and test results 90 days after each job.

Add the line and watch the second build

Connect GitHub

Card required. 3,000 minutes a month at 2 vCPU are included.