On this page
ADR-0011: Images built from verified upstream source onto a from-scratch root
Status: Accepted (plan decision D11). Implemented for the base image, the project template, nginx, PostgreSQL and Valkey.
Context
Images built FROM a distribution image inherit its package manager, shells and
network tools, and their versions follow the distribution, not upstream. Distroless
images drop the package database, which makes scanners blind to what is inside.
Decision
- The base image (
projects/base) installs a minimal Alpine package set into an empty root withapk --root, removes the package manager and copies that root into ascratchstage. The apk database is kept so that scanners identify packages. - Applications are built from the upstream release tarball, verified by SHA-256 (and by OpenPGP signature where upstream signs, as nginx does), in a build stage; only the results are copied into the final stage.
- The final image has no package manager, no compiler, no curl or wget, runs as
10001:10001, and works with a read-only root filesystem.
Consequences
- Exact upstream versions are possible, independent of Alpine's package versions.
- Runtime libraries come from Alpine packages added by
image/build/add-runtime-packages.sh, which merges the apk database without a package manager in the final image. - linux/amd64 builds are built and tested locally; linux/arm64 builds are expected to run on native CI runners and have not been executed yet.
- BusyBox had to be rebuilt to remove network applets properly (ADR-0020).
Amendment, 2026-11-10
- linux/arm64 has still not been built anywhere: the repository is private, and the
workflows build arm64 only when
CL_ARM64_RUNNERnames a runner or the repository is public (.github/scripts/platforms.sh, WP-70d). The release workflows refuse to release without arm64.