How to Shrink Docker Images: Multi‑Stage Builds, Distroless, Alpine & Guix
This article explains why Docker images often become oversized and presents several practical techniques—manual Dockerfile edits, multi‑stage builds, Google’s distroless images, Alpine Linux bases, and GNU Guix packaging—to dramatically reduce image size while balancing debugging convenience and security.
Docker images are often large, consuming disk space and bandwidth, especially at scale. Using the official Redis image as an example, this article introduces common methods to optimize Docker image size.
Manual Management
One can edit the Redis Dockerfile to delete unnecessary components and rebuild the image. While feasible, this approach is error‑prone, yields modest size reductions, and diverges from the official image.
Multi‑Stage Build
Since Docker 17.05, multi‑stage builds allow discarding intermediate layers, keeping only the components required for the final container.
Use a base image for the build stage.
Run commands to compile or assemble the application as usual.
Copy the needed artifacts into a separate, minimal image.
Distroless
Google’s distroless images contain only the application and its runtime dependencies, omitting package managers, shells, and other typical Linux utilities, which reduces attack surface and image size.
Using a multi‑stage build with a distroless base, the Dockerfile looks like this:
FROM redis:latest AS build
ARG TIME_ZONE
RUN mkdir -p /opt/etc && \
cp -a --parents /lib/x86_64-linux-gnu/libm.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
cp -a --parents /usr/local/bin/redis-server /opt && \
cp -a --parents /usr/local/bin/redis-sentinel /opt && \
cp /usr/share/zoneinfo/${TIME_ZONE:-UTC} /opt/etc/localtime
FROM gcr.io/distroless/base
COPY --from=build /opt /
VOLUME /data
WORKDIR /data
ENTRYPOINT ["redis-server"]Build and inspect the resulting images:
$ docker build -t redis:distroless .
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis distroless 7d50bd873bea 15 seconds ago 28.2MB
redis latest 1319b1eaa0b7 3 days ago 104MBThe image size drops from 104 MB to 28.2 MB.
Note: on Linux you can use ldd $(which redis-server) to list a binary’s dependencies.
Distroless images lack a shell, making container debugging difficult, but they improve security. In Kubernetes, tools like kubectl-debug can help with debugging.
Alpine Linux
Alpine Linux provides a minimal base using the musl C library instead of glibc, producing images around 30 MB. Unlike distroless, Alpine includes a shell, facilitating debugging, though musl may have performance differences compared to glibc.
GNU Guix
GNU Guix can create Docker images that contain only runtime dependencies, similar to distroless, but without manual dependency discovery. A single command builds the image:
$ guix pack -f docker redisThe resulting Redis image is about 70 MB. To include a shell for debugging, add bash:
$ guix pack -f docker redis bashGuix enables fully reproducible builds, making it suitable for CI/CD pipelines. Although Guix runs only on Linux, it provides its own Docker image, so you can use it via docker run guix. A similar tool, Nix, offers comparable capabilities.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
