Caching Composer or npm downloads previously meant a layer holding the cache directory, which bloats the image and is invalidated whenever anything above it changes.
# syntax=docker/dockerfile:1.1-experimental
FROM php:7.3-fpm-alpine
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/root/.composer/cache
composer install --no-dev --no-scripts --no-autoloader
The cache lives outside the image entirely and persists across builds, so a lock file change re-resolves without re-downloading eighty packages. The syntax line at the top is required — it selects a frontend that understands the flag, and forgetting it produces a confusing parse error rather than a helpful one. The cache is per-machine, so a fresh CI runner still starts cold; combining it with --cache-from against a registry image is what covers both cases.