Every file a package manager leaves behind ends up in an image layer, so container builds reward the smallest install. Compare three ways to add curl 3,008 to a base image. The Alpine 13,255 file is two lines, FROM alpine:3.24 and RUN apk add --no-cache curl; the careful Debian 319 version needs more ceremony, and a naive one drops the last two lines of the RUN.
FROM debian:trixie-slim
RUN apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*cd ~/v5-ch1/os-images
for f in alpine debian debian-naive; do
s=$(date +%s.%N)
docker build -q --no-cache -f $f.Dockerfile -t l1-curl-$f . >/dev/null
printf '%-13s %5.1fs\n' $f $(echo "$(date +%s.%N) - $s" | bc)
done
docker image ls --format '{{.Repository}}:{{.Tag}} {{.Size}}' \
| grep -E '^(alpine:3.24|debian:trixie-slim|l1-curl)'alpine 4.1s debian 13.4s debian-naive 20.4s l1-curl-debian-naive:latest 184MB l1-curl-debian:latest 136MB l1-curl-alpine:latest 20.8MB debian:trixie-slim 119MB alpine:3.24 13MB
On this shared 4-CPU machine Alpine finished in under a third of the careful Debian build's time, and its image is about a sixth of the size. The naive Debian build pays twice: apt-get update leaves its indexes in the layer, and without --no-install-recommends apt adds "recommended" packages (108 installed against 101). Node.js 2,131 images follow suit: node:24-alpine 242 MB, node:24-slim 332 MB, full node:24 1.65 GB. Docker 29 514 's containerd 234,762 image store counts compressed and unpacked layers together, so compare ratios, not Docker Hub 514 's figures.
Alpine's size has a price, and it is musl:
Native modules built for glibc do not load on musl. npm 2,036 packages with prebuilt binaries need a musl build (bcrypt and sharp ship them); others compile from source, which needs apk add python3 make g++.
DNS and locale behavior differ in edge cases, and some commercial tools support only glibc.
Docker weighs these trade-offs when it picks BookNest's base image (Planning Images), and Multi-Stage and BuildKit's multi-stage builds keep compilers out of the final image when you do need them.