Choosing a Base Image
The FROM instruction picks a base image; smaller bases like alpine and slim produce leaner, more secure images.
Every Dockerfile starts with a FROM instruction that chooses a base image. Your choice affects image size, security and how much you have to install yourself.
Common base image families
- Full distros —
ubuntu,debian: familiar and complete, but larger. - Slim variants —
debian:12-slim,python:3.12-slim: trimmed-down versions with fewer packages. - Alpine —
alpine: tiny (a few MB) but uses musl libc, which can occasionally cause compatibility quirks. - Distroless — images with no shell or package manager, for minimal attack surface.
- scratch — a completely empty image for statically compiled binaries.
Language-specific images
Official images like node, python and golang come with the runtime pre-installed, saving you setup work.
Example
# A tiny, statically-linked Go binary on scratch
FROM golang:1.22 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app
FROM scratch
COPY --from=build /app /app
ENTRYPOINT ["/app"]When to use it
- A security team mandates alpine-based images for all microservices to minimise the attack surface by reducing the number of installed packages.
- A developer switches from ubuntu to node:20-slim as the base image, cutting the final image size from 900 MB to 150 MB.
- A platform team maintains a hardened internal base image that all product teams must inherit from to ensure compliance.
More examples
Compare common base image sizes
Pulls three Node.js base variants so you can compare their sizes and choose the leanest suitable option.
docker pull node:20
docker pull node:20-slim
docker pull node:20-alpine
docker images | grep nodeScratch base for static binary
Uses the scratch base (empty filesystem) so the final image contains only the static binary, nothing else.
# Stage 1: build the Go binary
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -o /app .
# Stage 2: zero-OS image
FROM scratch
COPY --from=builder /app /app
ENTRYPOINT ["/app"]Use distroless base image
Distroless images contain only the runtime and its dependencies, with no shell or package manager to exploit.
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["dist/index.js"]
Discussion