A minimal base image sounded like an easy win and turned out to be a wash, because the extensions pull the libraries back in.
final image sizes, same application:
php:8.2-cli 482 MB
php:8.2-cli-alpine 142 MB
debian-slim + built exts 168 MB
distroless + built exts 151 MB
the extensions we need: intl, gd, zip, pdo_mysql, redis
intl alone brings ICU: 32 MB, unavoidable
and what distroless costs: no shell, so no exec into a
running container, and a debug variant to remember.
The nine megabytes between slim and distroless did not pay for losing a shell on a host where debugging happens by exec. Alpine is genuinely smaller and brings musl, which is a real consideration for anything doing locale work — we measured a difference in intl behaviour and stopped there. The size conversation is usually the wrong one: layer sharing means the base is pulled once.