npm ci in the images ran without frontend/.npmrc, so the eslint 9/10 peer conflict aborted it (legacy-peer-deps=true lives in .npmrc). The release build stage also used alpine/musl, where npm ci skipped the rolldown native bindings and vite build failed; build on glibc like dev instead.