Multi-Stage Docker Builds: Streamlining Containerization for Golang Applications

Multi-Stage Docker Builds: Streamlining Containerization for Golang Applications

Learn How to Reduce Docker Image Size by 800%

Β·

4 min read

Docker has revolutionized program packaging and distribution, making it easier than ever to assure consistency across several environments. The ability to make multi-stage builds is one of Docker's most powerful capabilities. This method allows developers to optimize Dockerfiles for size, security, and speed, which is very useful when working with Golang apps. In this blog article, we'll look into multi-stage Docker builds, beginning with an overview and then comparing the benefits of utilizing them with Golang apps to standard single-stage builds with a practical working project.

Introduction to Multi-Stage Docker Builds:

Docker containers are self-contained, lightweight entities that encapsulate a program and its dependencies. A Dockerfile, which describes how to generate the container image step by step, is often defined when creating a Docker image. Each step in the Dockerfile creates a layer in the final image, which might waste disk space and have an influence on security and performance.

Docker multi-stage build with example - Programmer Lib

Multi-stage builds address these issues by allowing you to define numerous stages in a single Dockerfile, each serving a distinct function. These phases can assist you in compiling, packaging, and optimizing your program, and the final image only contains what is required to operate the application, removing unneeded bloat.

The Standard Single-Stage Approach:

A single-stage Docker build for a Golang application would generally begin with a base image including the Go runtime and build tools. Then you paste your source code inside the container, compile it, and package it.

While this method is effective, it may result in a bigger image size because the final image contains not only your generated binary but also the build tools, source code, and maybe additional artifacts that are not required at runtime.

This can have an impact on security while also increasing picture dissemination time and storage expenses.

The Multi-Stage Method

Multi-stage builds for Golang apps are intended to address the shortcomings of single-stage builds. This is how it works:

Building thin Docker images using multi-stage build for your java apps!

  1. Builder Stage: In the first stage, you compile your Golang program using an image that includes the Go runtime and build tools. This stage generates a lightweight image containing simply the compiled binaries.

  2. Final step: In the second step, you generate the final runtime image for your program using a basic base image, such as a scratch or an Alpine Linux image. The binary is copied from the construction step to the final stage. Because the build tools and extraneous files are not included in this step, the resultant image is smaller and more secure.

Practical Comparison:

The key reason for selecting a Golang-based app to demonstrate this example is that Golang is a statically typed programming language that does not require runtime in the conventional sense. In contrast to dynamically typed languages such as Python, Ruby, and JavaScript, which require a runtime environment to execute their code, Go compiles straight to machine code, which can then be executed directly by the operating system.

So the true benefit of multi-stage docker build and distroless images can be understood by a substantial reduction in image size.

Traditional Approach:

To choose the Dockerfile without multi-stage, we first navigate to our repository and then proceed to construct a basic image as follows:

Run the following command to

docker build -t cacl .

The Image size for a simple calculator is quite huge, as you can see. (864 MB). This emphasizes the need to use multi-stage builds to successfully minimize the image's size.

Multi-Stage Approach

We can enhance the Dockerfile by splitting it into two distinct stages: Stage 1, which creates the base image, and Stage 2, which handles the multi-stage build process.

Distroless images, also known as "minimalist containers" or "distroless containers," are containerization and container-based application deployment ideas. These images are intended to be as light and simple as possible, having only the components needed to operate a given application or service, rather than a full operating system or standard Linux distribution.

Following the successful build of this image, we can now observe the following:

We can clearly see a significant reduction in image size, which is around 800 times smaller than the original.

Note that, This case is only for the Golang applications since it is a statically typed language and hence doesnt need run time execution unlike Python or Java apps which would need Python library and OpenJDK ide respectively

Conclusion

It can be concluded that multi-stage Docker builds provide a great technique for constructing more efficient and optimized container images. While GoLang programs benefit from their modest binary size by default, using multi-stage builds improves their performance even further.

You can verify that your Dockerized GoLang apps are ready for production with little overhead by decreasing image size, enhancing security, and speeding up builds.

Consider the benefits of multi-stage builds the next time you containerize your GoLang application, and watch your Docker images become leaner and more efficient than ever before.

References:

https://docs.docker.com

Thank you for reading the blog.πŸ™ŒπŸ»πŸ“ƒ

πŸ”° Keep Learning !! Keep Sharing !! πŸ”°

πŸš€ Feel free to connect with me :

Β