On this page
Why Is Your Docker Image So Large (and How Do You Shrink It)?
A 1.5 GB Docker image is usually build cruft, not your app. Learn the four causes and the fixes that routinely cut images by 80%.
Quick answer
- Most of a fat Docker image is build tools and caches the final app never needs.
- Multi-stage builds — build in one stage, copy only the artifacts into a slim runtime stage — are the single biggest win.
- Check layer sizes with docker history; one unnecessary COPY or apt install can add hundreds of MB.
Why is my Docker image so big?
The usual causes, in order of size: you start from a fat base image (python:3.12 instead of python:3.12-slim or an alpine variant); you install build tools (compilers, package managers) that only exist to compile dependencies; you copy the whole project including node_modules or .venv; and you never clean apt or pip caches. Each layer is permanent — deleting a file in a later layer doesn’t remove it from the image, it just hides it. That’s why ‘I removed the cache’ sometimes changes nothing.
# Before: one big image with everything
FROM python:3.12
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
# After: multi-stage — build tools never reach the runtime image
FROM python:3.12-slim AS builder
COPY requirements.txt /
RUN pip install --prefix=/install -r requirements.txt
FROM python:3.12-slim
COPY --from=builder /install /usr/local
COPY . /app
WORKDIR /app
CMD ["uvicorn", "app:app"]How do I find out what’s taking space?
Run docker history –no-trunc After the changes, docker images should show your image at a fraction of its previous size — commonly 100-300 MB instead of 1.5 GB for a Python or Node app — and the app must still build and run identically. Verify the container starts and the app responds before celebrating the smaller size; a shrunken image that crashes at startup is a regression, not an improvement. Where this bites vibecoders AI assistants generate working Dockerfiles that are almost never small: they copy the whole repo, install everything, and skip .dockerignore. The result is a 1.5 GB image that takes minutes to build and push, exhausts free container registries, and slows every deploy. Asking the assistant for a ‘multi-stage build with a slim base’ fixes most of it, and the size check (docker images) makes the improvement visible immediately. Less than for frequent deploys, but still yes: smaller images pull faster on cold starts, use less registry and disk space, and have a smaller attack surface. The effort is a one-time Dockerfile change, so the cost of doing it is near zero. Alpine is a minimal Linux distribution using musl libc; slim variants are the official image with the documentation and common packages stripped out. Alpine images are smaller, but some Python/Node packages need musl-specific builds. Try slim first — it’s the same distro with less cruft and rarely breaks anything.What does ‘it worked’ look like?
Where AI coding assistants get this wrong
Checklist
FAQ
Does a smaller image matter if I only deploy once?
What is the difference between alpine and slim base images?
Related topics
Sources