Containers & Orchestration

Docker Image Slimming: 5 Steps from 1.2GB to 120MB

Bigger images mean slower pulls, larger attack surface and higher storage cost. This guide gives 5 immediately applicable slimming steps, each with a reusable Dockerfile snippet and a verification command.

By LaoHand Team·7 min read·Updated 2026-08-24

Measure first: where is the fat

Before touching anything, check the size with `docker images`, then analyze each layer with `dive` to see what was added where. No measurement, no direction.

docker images
# 或逐层分析:
dive <image>

Step 1: smaller base image

Swap `ubuntu`/`debian` for `alpine`, `slim` or `distroless`. This alone often cuts hundreds of MB. Note alpine uses musl libc, so some binaries may need recompiling.

FROM node:20-alpine   # 而非 node:20(基于 debian)

Step 2: multi-stage build

Put build dependencies in a build stage and COPY only the compiled artifact into the final image. The runtime stage does not need gcc or full node_modules source.

FROM golang:1.22 AS build
RUN go build -o app .
FROM gcr.io/distroless/static
COPY --from=build /app /app
ENTRYPOINT ["/app"]

Step 3: do not skip .dockerignore

Without `.dockerignore`, `COPY . /app` packs node_modules, .git and local logs into the image. Add an ignore list to save space immediately.

node_modules
.git
*.log
.env

Step 4: merge RUN and clean caches

Each RUN is a layer. Put install and cleanup in the same RUN so you do not leave "installed then deleted" bloat in an earlier layer.

RUN apt-get update \
 && apt-get install -y --no-install-recommends curl \
 && rm -rf /var/lib/apt/lists/*

Step 5: verify and lock in

After rebuilding, compare sizes with `docker images`, then bake the best practices into your project template so it does not bloat again.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.