Creating a minimal container image for a Go application

Lucas Jellema
3 min readMay 3, 2022
Build executable from Go source code and build Container Image from Alpine base image with binary executable

How hard can it be — to create the smallest possible container image to run a Go application? It is not hard to create a container image that contains an binary executable file — and that is what a Go application turns into during the build process. However, that does not automatically produce a very small image or one that actually can run the application successfully. There are a few things to consider, as I found out during a few frustrating hours.

In the end it is all simple enough. When you know what to do, then it is all quite simple. Obviously.

What I had to learn:

  • a Go application built just like that in my Ubuntu environment will not run just like that in an Alpine based container image; it should not have been a surprise, but still I had not considered this
  • a Go application should be built with statically linked dependencies — to make runtime behavior not dependent on libraries being present (at all or in the expected location); you’ll enable a statically linked binary by setting CGO_ENABLED=0
  • the binary executable can be created a little smaller by stripping off the debugging symbols; this done using compile flags -ldflags=”-s -w”
  • in order to make HTTPS calls from the Alpine image it is required to have (recent) details for certificate authorities loaded into the container image

The Go build command I use to create the binary executable that will find its way into the container:

CGO_ENABLED=0 GOOS=linux go build -o person-producer -ldflags="-s -w"

I run this command in the directory that contains the Go source file with the main package. person-producer is the name of the executable file that is the result of the build process; it is a standalone binary executable file of about 6MB.

The container image is built from a Dockerfile called `DockerfileAlpine`; it is located in the same directory as `person-producer.go`. It has the following content (to be processed to produce the small container image I am hoping for):

FROM alpine:latestWORKDIR /app# add ca-certificates to allow signed communications
Lucas Jellema

Lucas Jellema is CTO and IT architect at Conclusion, The Netherlands. He is Oracle ACE Director, one time JavaOne Rockstar and programmer