Introduction
Image is one necessary thing that you must plan when you want to containerize your apps. Building a large image means you need more data to transfer between your image repository, CI/CD platform, and deployment server. Creating a smaller container is a must to save time. There’s no need to be difficult when it comes to reducing container image size. Especially with Go apps, it has already come with a binary, which means it doesn’t need any environmental server like Nginx, Node, Etc.
In this article, you will learn how to reduce your Go apps container image using Docker. You can also use another builder like Buildah that used by Podman. In this case, you will reduce your container image’s size using a multi-stage build with a distroless image, UPX, and especially for Go apps, utilize the ldflags.
Go Apps
For example, you have a Go application like below:
|
|
Import the httprouter to help simulate the go mod download
command inside the Dockerfile
/Containerfile
.
Initial Dockerfile
Let’s say here is your initial Dockerfile content:
|
|
Tips: You can optionally use an alpine image to reduce your base image to save data. And utilize the builder cache by properly putting the line that changes less often earlier.
Let’s build and tag it as example:initial
.
|
|
It takes 337MB, let’s improve it.
Multistage Dockerfile
|
|
Multistage build helps you to leave all the unimportant things inside the base image and start using a new image to run your apps.
|
|
As you see, you can name your stages so if you want to copy things from that stage, you can provide the stage’s name on the COPY
line.
|
|
Also, you can use a distroless image as your runner image to make your container image smaller. It is also available for some other programming languages. According to its documentation:
“Distroless” images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.
As for the example you use CGO_ENABLED=0
flags, you can use the gcr.io/distroless/static
as a runner image. But if you need the flags to be on, you should use gcr.io/distroless/base
referring to the docs.
Let’s build again and tag it as example:multistage
.
|
|
Do we have room to be improved? Of course!
UPX Dockerfile
|
|
UPX is a tool to help you shrink your binary size, not only specific for Go apps. You can install the UPX
on line 4, and run the UPX
command on line 13 to utilize the builder cache. upx -9
means you want to compress better, you can see the available flags by using upx -h
.
Let’s build again and tag it as example:with-upx
.
|
|
Not bad, isn’t it? Let’s do the final touch.
Utilize Go Flags
|
|
Using your last Dockerfile, you only need to retouch the go build
command. Add the -ldflags "-s -w"
flags to disable the symbol table and DWARF generation that is supposed to create debugging data. You can see the other available options using the go tool link -h
command.
Let’s build and tag it as example:latest
.
|
|
There you have a minimalist Go apps container image with a significant reduction.
Conclusion
You can also use the steps in this article to build another container image besides Go apps. Especially the multistage build that reduce more than half of the image size. But still, only you know what’s best and fit for you.
Thank you for reading!