Reducing Docker Image Size by 70% in Spring Native and Golang Projects with Upx
Hi, In this article, I will explain how we can reduce the docker image size by 70% using upx in spring native and golang projects.
What is UPX(Ultimate Executable Packer)
UPX is an advanced file compressor that compresses executable files. UPX typically reduces the file size of programs and DLLs by about 50–70%, reducing programs’ disk space, network load times, download times, and other distribution and storage costs.
When spring native or golang projects are compiled, since they produce executable programs directly, we can reduce the size of these programs by 50–70% with upx.
Reducing Docker Image Size with UPX in Golang Projects
The docker image size of the web service I developed using the echo framework written in Golang was 40 MB. I reduced the image size to 5.05 MB by making some adjustments to the dockerfile.
The Dockerfile is as follows.
ARG upx_version=3.96 : Upx version to be installed. Currently the most updated version.
CGO_ENABLED=0 : you have a statically linked binary file. so it works without any external dependencies. In the scratch docker image, it makes our application run.
GOOS=linux: the compiler compiles the application to the linux operating system.
GOARCH=amd64: it tells the compiler that it must conform to the amd64 processor architecture.
ldflags=”-s -w” : removes debug information from the binary file.
RUN upx — ultra-brute -qq server && \upx -t server : we compressed the executable using upx.
FROM scratch: zero size out of the box docker image. This means that the resulting image size is equal to the binary size.
COPY — from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt : adds root certificates to struct docker images.
CMD [“./server”] : runs the application.
Let’s create docker images of the application.
$ docker build -t app:1.0.0 .
The docker image size of the application is 5.05 mb
Reducing Docker Image Size with UPX in Spring Native Projects
We can compile Spring Boot application as native with Spring native.When I compiled the application as native, the docker image size of the web service was 169 MB. I made some adjustments in the spring-boot-maven-plugin and reduced the image size to 53.4 MB.
The pom.xml is as follows.
<java.version>17</java.version> : the application was compiled according to Java 17
<spring-native.version>0.11.0-RC1</spring-native.version> : the current most up-to-date spring native version is compatible with spring boot 2.6.1.
<name>docker.io/suayb/native-app:1.0.0</name> : the tag of the docker image to be created.
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE> :the native image build pack is enabled. In Spring Native 0.11, the Liberica Native Image Kit (NIK) is the native image compiler distribution used by default with Buildpacks.
<BP_BINARY_COMPRESSION_METHOD>upx</BP_BINARY_COMPRESSION_METHOD>: it creates a compressed executable using upx. Required to be able to reduce the docker image size.
— enable-https — enable-http : http and https are enabled as url protocols.
<publish>false</publish> : does not publish the created image in the docker registry.
<pullPolicy>IF_NOT_PRESENT</pullPolicy> : if the builder docker images do not exist locally, it pulls. This value is ALWAYS by default.
Let’s create docker images of the application.
$ mvn spring-boot:build-image
The docker image size of the application is 53.04 mb.
My article ends here. As seen with Upx, we can reduce docker image sizes by 70%. In Docker, we prefer small size image sizes because of the disposability principle. Because large containers take a long time to stand up.
Image size doesn’t affect your program’s performance, but it can speed up many processes.
See you in the next articles.