DevOpsInterviewPrep logo
Containers & Kubernetes / 08
medium★ EssentialNewRed HatGitLabShopify

A service image is 1.2GB and deploys are slow. Get it under 100MB without breaking it.

A practical question with a precise answer, and the size is not the real cost. Pull time on every node, registry storage, and attack surface all scale with it.

Updated Sep 2026 · Grounded in researched DevOps, SRE and platform engineering interview loops, written to a senior-engineer editorial bar, and never padded to hit a word count.

TL;DR: Multi-stage build, minimal runtime base, and a .dockerignore. Compile in a stage that has the toolchain and copy only the artifact into a distroless or Alpine runtime. Whether 100MB is achievable depends on the runtime and assets; measure the layers before promising that target.

How to approach it

Say where the weight actually is before optimising, then give the change in order of return. Finish on why size matters beyond storage, since that is what makes it a senior answer rather than a tip.

A strong answer

First find the weight:

docker history --no-trunc myapp:1.2 | head -20

That lists image history with layer sizes, in history order rather than sorted by size. Look for a full OS base image, a language SDK, a package manager cache, and the source tree, none of which the running process needs.

Multi-stage build is the structural fix and it does most of the work:

FROM golang:1.27.1 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server

FROM gcr.io/distroless/static-debian12
COPY --from=build /app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]

The build stage keeps the compiler and module cache; the final image contains one binary. The final size depends on the binary, libraries and runtime data. Use a supported toolchain and pin production base images by reviewed digest; Go’s release history lists support and patch versions. For an interpreted language the runtime has to come along, so the target is more like 80 to 150MB with Alpine or a slim base, and the win comes from excluding dev dependencies and build tools rather than everything.

Base image choice in order of size and awkwardness. Distroless has no shell and no package manager, which reduces bundled tooling but is not universally smallest or most secure. A shell-based exec session is unavailable, so you need ephemeral debug containers. Alpine is small and uses musl rather than glibc, which occasionally breaks native extensions and has caused real DNS resolution differences. A slim Debian variant is the safe middle. Pick deliberately and say why.

Layer ordering matters for build speed rather than final size, but it belongs in the answer: put the least frequently changing instructions first, so dependency installation is cached and only the source copy invalidates. Copying the whole source before installing dependencies means every code change reinstalls everything.

.dockerignore stops the build context carrying .git, node_modules, test fixtures and local artifacts into the daemon, which both slows the build and often ends up inside the image by accident.

Now why it matters beyond the number. Every node that lacks the required cached layers must pull them, so pull time is on the critical path of every scale-up and every reschedule, which is exactly when you are already under pressure. On a 200-node cluster a 1.2GB image is a lot of bandwidth per rollout. And image size correlates with attack surface: a shell, a package manager and a hundred OS packages are all things a scanner will flag and an attacker can use.

What interviewers probe next

"How do you debug a distroless container?" kubectl debug with an ephemeral container sharing the process namespace. The tooling lives in the debug image, not in production.

"What is a scratch image?" Empty. Works for a static binary with no CA certificates or timezone data; add those explicitly or TLS calls fail in a way that looks unrelated.

"Does a smaller image start faster?" The pull is faster, which dominates on a cold node. The process start is unchanged.

Common mistakes

Deleting files in a later RUN layer to shrink the image. Layers are additive, so the data is still in the earlier layer and the image is no smaller.

Choosing Alpine reflexively and meeting musl incompatibilities in production rather than in test.

Optimising the number to look good while ignoring that the real payoff is pull time during a scale-up.

That one was free, and so are 10 answers per topic without an account. Signing in doubles that to 20, keeps your bookmarks, and tracks which topics you keep getting wrong.one Google click · no card · nothing to cancel
HOW DID IT GO?
0
UP NEXT ON YOUR JOURNEY
DISCUSSION · 0

Nothing here yet. Say how you would answer it.