BuildKit cache mounts for composer and npm

A layer cache is invalidated by a lock file change; a cache mount survives it, because the downloaded packages are not in the layer at all.

# syntax=docker/dockerfile:1.3

RUN --mount=type=cache,target=/root/.composer/cache 
    composer install --no-dev --prefer-dist --no-progress

RUN --mount=type=cache,target=/root/.npm 
    npm ci --no-audit --no-fund

# adding one package now re-downloads one package,
# rather than all 340.

The syntax directive at the top is required and is the thing people forget, at which point the --mount flag is a parse error rather than a silent no-op — a good failure. The cache is per builder rather than in the image, so it does nothing for a pipeline that starts on a fresh runner unless the builder cache is itself exported; the GitHub Actions cache backend covers that. It also means the build is no longer reproducible from the Dockerfile alone, which is a real trade for a real speedup.