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 巧匠 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.