How to make docker images smaller

One of the best practices when working with Docker is to create lightweight images. That’s because smaller Docker images result in faster deployments and are easier to ship, if required. You can keep your Docker image sizes under control with the following methods:

Method 1: Multistage Build

A multistage build means that you can use multiple base images in your Dockerfile with the help of FROM statements. In the first base image, you can build the packages of your application, then simply copy the required binaries and configurations to the final image. You can use as many FROM statements as you need.

Start by giving a name to the very first FROM statement. That way, you can use this name in your next FROM statement as a base image, and each of these FROM statements will start a new build stage. You can selectively copy the necessary files/folders from the first stage to the second stage, which serve the purpose of running the application. Below is an example of a Golang Dockerfile:

FROM golang:1.11 as buildstage1
WORKDIR /Users/put/IOD
COPY main.go .
RUN go build -o server .
FROM debian:stretch
WORKDIR /Users/put/IOD
COPY --from=buildstage1 /Users/put/IOD .
CMD ["./server"]

With the multistage build technique, the size of the final image is 107MB, while the original image size was 803MB.

Method 2: Distroless-Based Images

Distroless-based images are images that contain only your application/software, plus any related dependencies. They don’t contain any operating systems, so there are no bash shells, package managers, etc. in these images.

You can get distroless-based images from Google Cloud’s Container Registry. In the below example, we are using the Golang Dockerfile used previously (in Method 1).

FROM golang:1.11 as buildstage1
WORKDIR /Users/put/IOD
COPY main.go .
RUN go build -o server .
FROM gcr.io/distroless/base
WORKDIR /Users/put/IOD
COPY --from=buildstage1 /Users/put/IOD .
CMD ["./server"]

With distroless-based images, the size of the final image is 65MB, much less than the final size of the multistage build image (107MB).

Method 3: Alpine-Based Images

Alpine Linux is a musl libc and BusyBox-based Linux distribution. It is by far the smallest, simplest, and most secure Linux distribution on the market. The size of the Alpine distro starts at only 5MB. This means that by using Alpine as your base image, your Docker images will be even smaller than those created by distroless-based images. With Alpine-based images, your Golang Dockerfile will look like this:

FROM golang:1.11-alpine3.7 as buildstage1
WORKDIR /Users/put/IOD
COPY main.go .
RUN go build -o server .
FROM alpine:3.7
WORKDIR /Users/put/IOD
COPY --from=buildstage1 /Users/put/IOD .
CMD ["./server"]

Note that the size of the Docker image generated from the Alpine-based image (10.8MB) is even smaller than the distroless-based image (65MB).

Last updated