Skip to content

ci(docker): build on self-hosted runner with a warm BuildKit cache - #86

Merged
mo4islona merged 1 commit into
masterfrom
ci/persistent-docker-build-cache
Jul 14, 2026
Merged

ci(docker): build on self-hosted runner with a warm BuildKit cache#86
mo4islona merged 1 commit into
masterfrom
ci/persistent-docker-build-cache

Conversation

@mo4islona

Copy link
Copy Markdown
Contributor

Problem

The docker workflow (manual hotblocks/archive image builds) ran on ubuntu-latest with no build cache. Every dispatch recompiled the entire Rust dependency graph from scratch. Three compounding causes:

  1. DockerfileADD crates before a single monolithic cargo build, no cache mounts → any source change recompiles all deps.
  2. Workflowubuntu-latest (ephemeral) + build-push-action with no cache-from/cache-to.
  3. Runner host — a nightly docker system prune -a -f --volumes (see companion dev-server PR).

Change

  • Dockerfile: BuildKit cargo cache mounts on registry/git (shared) and target/ (per-arch id=cargo-target-$TARGETARCH, sharing=locked). Binaries are copied out of the target/ cache mount to /out for the runtime stages. Only changed crates recompile now.
  • Workflow: runs on [self-hosted, dev-server] (safe — workflow_dispatch-only, maintainer-triggered), reuses a persistent named buildx builder dev-server-cache (keep-state, cleanup: false) so the cache survives across jobs, caps it at 15GB via BuildKit GC, and adds QEMU for arm64.
  • Default platformslinux/amd64 (arm64 stays available per dispatch). Keeps the cache to a single target dir, which matters on this disk-constrained host.

Requires

  • subsquid/data must have access to the dev-server runner group.
  • Companion PR in subsquid/dev-server (github-runner role) to stop the nightly prune from wiping the builder cache — merge/apply that too, else the cache won't survive the night.

Sizing (measured on a real Linux release build of this repo)

target/release ≈ 1.5GB, cargo registry ≈ 1.9GB, base image/layers ≈ 5GB → ~9GB for one arch. 15GB cap leaves comfortable headroom.

🤖 Generated with Claude Code

The docker image build ran on ubuntu-latest with no build cache, so every
hotblocks/archive image recompiled the whole Rust dependency graph from
scratch.

- Dockerfile: add BuildKit cargo cache mounts (registry/git + per-arch
  target/) so only changed crates recompile; binaries are copied out of the
  target cache mount to /out for the runtime stages.
- workflow: run on [self-hosted, dev-server] (safe: workflow_dispatch-only),
  reuse a persistent named buildx builder (keep-state) so the cache survives
  across jobs, cap it at 15GB via BuildKit GC, add QEMU for arm64.
- default platforms to linux/amd64 (arm64 opt-in per dispatch) to keep the
  cache to one target dir on the disk-constrained host.

Pairs with subsquid/dev-server: the github-runner role must stop the nightly
`docker system prune --volumes` from wiping the builder's cache volume.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mo4islona
mo4islona merged commit 0f33174 into master Jul 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant