jolicode / jolicode/docker-starter
Intermittent type=registry cache misses in CI (mode=max cache-to) — consider type=gha for CI builds
- Dominant language
- PHP
- Stars
- 358
- Forks
- 35
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 10
Description
## Context
The template's CI (`ci.yml`) and `castor docker:push` (`cache.yml`) cache the `frontend`/`builder` images through a registry-based BuildKit cache (`type=registry,ref=...:cache`, `cache-to ...,mode=max` — see `docker\push()` in `.castor/docker.php` and the `cache_from` entries in `infrastructure/docker/docker-compose.yml`).
## What we observed
On a downstream project using this template (single PHP version, no matrix), CI intermittently fails to hit this cache on some layers of the `builder` target — most visibly the very first builder-only step (`RUN apt-get install git make php-dev sudo unzip`, right after `FROM php-base AS builder`). We compared several CI runs with byte-identical Dockerfile content (verified via `git show :.../Dockerfile`) and a cache freshly pushed minutes earlier:
- some runs get an instant `CACHED` for that step
- other runs, same Dockerfile, same recent cache, re-run `apt-get install` in full (~15-30s), with no error or warning printed anywhere in the log — it's a silent fallback to a full layer rebuild
We ruled out:
- a stale branch (Dockerfile content confirmed identical across all compared branches)
- auth (surrounding layers from the same cache manifest do import fine in the same build)
- PHP-version mismatch — this project only builds one PHP version, unlike this repo's own CI matrix (8.3/8.4/8.5), which incidentally masks the same class of issue: only the PHP 8.5 matrix job matches the pushed cache (built with `DS_PHP_VERSION: "8.5"`), so the 8.3/8.4 "misses" always look like a plain version mismatch rather than the intermittent behavior described here.
## Likely cause
This matches a known class of BuildKit/registry cache-import flakiness with `type=registry` + `mode=max`: resolving some blobs of a cache manifest occasionally fails silently, falling back to rebuilding that layer (and everything after it in the same stage).
## Question for maintainers / community
Docker's own docs recommend `type=gha` (native GitHub Actions cache) over `type=registry` specifically for GitHub Actions builds, precisely because of this kind of inconsistency: https://docs.docker.com/build/cache/backends/gha/. `type=registry` would still be needed for the local dev cache (that's what `castor docker:push` / `cache_from` is for), but CI could additionally use `type=gha` as a CI-only cache-from/cache-to (e.g. via a CI-scoped compose override).
Has anyone else hit this? Is it worth adding `type=gha` for the CI build specifically, or is the occasional slower CI build acceptable given the added complexity (another compose override, CI-only cache-to)?
Contributor guide
Research direction
Start by reading the cache configuration in ci.yml, .castor/docker.php, and infrastructure/docker/docker-compose.yml, including the docker\push() and cache_from entries. Reproduce or compare CI builds that miss the builder cache, then evaluate a CI-only type=gha configuration while preserving the registry cache used by local development. Done means the maintainers agree on the design and CI cache behavior is validated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, docker-compose, github-actions, php
- Domain
- build-system, ci-cd, devops
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100