How I’ve reduced my Golang Docker image size by 98,7 %

Niko Diamadis
2 min readDec 23, 2024

--

Photo by frank mckenna on Unsplash

For my Matrix Security Bot “Matrix Guardian” I chose to use Golang. Simple distribution can be done with Docker images, so I started building a Dockerfile for my project.

For the base image the straight forward choice is https://hub.docker.com/_/golang.

The first Dockerfile looks like this:

It is a very basic build with a build time of 37 seconds and is pretty huge with 1010 Megabytes.

A smaller base image than “golang:latest” is based on a minimal Alpine Linux, therefore called “golang:alpine”:

This change reduced the image size to 575 Megabytes with 46 seconds of build time. Depending on your dependencies you may need “gcc” to compile native libraries, in my case the golang sqlite library, as “gcc” is not bundled in Alpine Linux.

Additionally I had to add the compiler flag “CGO_ENABLED=1” to be able to use the sqlite library, which again depends on your project setup.

The last very important optimization is the idea of multi-stage builds. In short that means to use one base image to build the golang executable and another (usually smaller) base image to actually run the executable to effectively reduce the image size and runtime overhead.

For the runtime base image I choose “scratch”, it is the smallest possible base image.

Now we are down to an impressive size of 13 Megabytes. Besides defining the scratch runtime we have to apply some more fixes.

On the one side we have to manually copy trusted TLS certificates over to the runtime to allow verified TLS traffic.

On the other side, because “scratch” doesn’t even support RUN commands, we have to create necessary directories from within the builder image that we then copy over to the runtime image.

So that was it, the result is a very lightweight image.

I hope you learned something new, cheers 👋.

--

--

Niko Diamadis
Niko Diamadis

Written by Niko Diamadis

Student & Freetime Android developer

Responses (2)