# Docker layer caching

> Latchkey Docker Cache Build wraps docker buildx with registry-backed layer caching, so repeat image builds reuse every unchanged layer across ephemeral runners.

Source: https://latchkey.dev/documentation/docker-layer-caching

## Summary

- One step: `latchkey-dev/docker-cache-action@v1` wraps `docker buildx build` with registry-backed layer caching.
- Layers persist across Latchkey's single-use runners; only the layers your changes invalidate get rebuilt.
- Zero setup: the cache registry, credentials, and permissions are pre-provisioned per organization.
- Portable: on non-Latchkey runners the same step detects no registry and builds normally, without cache flags.

Every Latchkey runner is a fresh, isolated instance. That is good for security and bad for Docker's local layer cache, which disappears with the runner. **Latchkey Docker Cache Build** solves it with a layer cache stored in a private container registry managed by Latchkey for your organization: matching layers from earlier builds are reused, and the updated cache is written back for the next run.

## Add it to your workflow

```.github/workflows/build.yml
jobs:
  build:
    runs-on: latchkey-medium
    steps:
      - uses: actions/checkout@v4
      - uses: latchkey-dev/docker-cache-action@v1
        with:
          context: .
          tags: myapp:latest
          push: true
```

That is the whole integration: you supply the inputs you would give any Docker build, and Latchkey handles the registry, the credentials, and the cache wiring. By default the action uses `cache-mode: max`, which caches all layers including intermediate layers from multi-stage builds. Single-platform builds with `push: false` load the built image into the runner's local Docker daemon.

## What layer caching is worth: a worked example

Illustrative numbers, not a measured benchmark. Take a multi-stage Node.js image that builds in ~8 minutes uncached: base image, system packages, dependency install, compile, assemble. With the layer cache in place, a source-only change invalidates just the final layers; everything above them is pulled from the registry cache, and the rebuild lands in the **1 to 2 minute range**. A commit that touches the dependency stage invalidates more layers and rebuilds more, so the win scales with how much of your Dockerfile a typical change leaves untouched. The default `cache-mode: max` trades a bigger cache push after the build for better hit rates on exactly these multi-stage rebuilds, since intermediate stage layers are cached too.

## Inputs and outputs

| Input | Default | What it does |
| --- | --- | --- |
| `tags` | required | Tags for the built image |
| `context` | `.` | Build context path |
| `dockerfile` | `Dockerfile` | Path to the Dockerfile |
| `push` | `false` | Push the built image |
| `build-args` | none | Build arguments; values are masked in logs since they may contain secrets |
| `target` | none | Target stage for multi-stage builds |
| `platforms` | none | Target platforms for the build |
| `cache-mode` | `max` | Cache scope: `min` or `max` (max caches all layers, including intermediate multi-stage layers) |
| `cache-tag` | `cache` | Registry tag used for the layer cache |
| `extra-cache-from` / `extra-cache-to` | none | Additional cache sources and destinations passed to the build |

| Output | What it tells you |
| --- | --- |
| `cache-configured` | `true` when registry layer caching was active for the build, `false` otherwise |
| `image-digest` | Digest of the built image |

## Safe on any runner

- **On non-Latchkey runners** (for example GitHub-hosted), the action detects the cache registry is not available and builds normally, without cache flags. One workflow file stays portable across runner types.
- **On a repository's first build** the cache is empty; if a cached build fails on that first run, the action automatically retries without cache. First runs never break because of caching.
- **Build-arg values are masked** in logs, so secrets passed as build args do not leak into job output.
- Caches are **isolated per organization**.

> ****
> Pair this with a [custom AI Scan runner](/documentation/custom-runners) that pre-pulls your base images, and image builds skip both the pull and the unchanged layers.

### How does Docker layer caching work on ephemeral runners?

`latchkey-dev/docker-cache-action@v1` wraps `docker buildx build` with a registry-backed layer cache, so layers persist in a registry rather than on the machine. Each single-use runner pulls the layers your change did not invalidate and rebuilds only the ones it did.

### Do I have to configure a registry or credentials?

No. The cache registry, its credentials and the permissions are pre-provisioned per organization, so the step works with no setup. There is nothing to create and no secret to add.

### Does the action still work on non-Latchkey runners?

Yes. On a runner with no Latchkey cache registry available the step detects that and runs a normal `docker buildx build` without cache flags, so a workflow shared across runner types does not need branching.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
