Multi Stage Docker
In our previous post about Docker, we have built an image with a simple Golang apps inside of it. We created it from golang:latest
as a base image taken from the official Docker Hub. And yes, it was running perfectly. But if we see more detail, we will find that the size of the image is so big. And of course we don’t want to save an image (that only contains a simple application) with that size in our local registry.
The Challenge!
If I have to build and save many Docker Images with that size in my local registry, where should I save my downloaded blu-ray movies then?
Well.. ummm.. that’s…. wow what a challenge!
The Better Challenge!
How can we minimize the size of the Docker Images so there will be a lot of space in my storage so that I can use to save my ummm…. kids photos?
Well, ok.. whatever.
This is why we need a Multi Stage Docker!
The idea is simple, it is like we use one computer that contains everything we need to build our apps, in this case a Golang development environment. Then we build the code there to produce a binary file. Once complete, we copy that binary file (and some other needed files too) to another very basic clean computer. We don’t need any libraries or dependencies to be installed in this computer, all we need is just making the service running there. Well maybe in some cases, we still need something to be installed too, but it should be not as complex as what’s in the first computer. So we will find the size of second computer is not as big as the first computer, even way smaller. And that second computer that will be our Docker image.
First, Knowing Our Base Image
Since we use golang:latest
as our base image, let’s get a little closer about it so we have a better understanding about what we are using on. Let’s go to the official golang repository on Docker Hub and get acquainted. We’ll see our base image’s size there.
Yes, it is 295 MB. But don’t be surprised now, it is only the compressed size. What about the uncompressed size? Let’s take a look again to our docker images list, because actually we pulled the golang:latest
image from Docker Hub and extract it into our local registry when we built our latest container.
Now you may be surprised, it is 774 MB! No wonder if our dockerizedgoapp
image’s size is more than that.
Use Very Basic Base Image
From the 2 computers analogy above, I believe we have a better perspective now. So we will use golang:latest
(first base image) as a specification for the computer no 1, which will build our application and produce the executable binary file. Now what about the computer no 2 ? what will we use for that?
Let’s say thanks to : alpine. A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!
We can find it in the Docker Hub official repositories. It is lightweight and very commonly used as a base image of Docker container. And if you follow some tutorials about Docker for beginners on Google or YouTube, most of them will use this image for their first Docker container.
So let’s start modifying our Dockerfile
now.
It’s beautiful, isn’t it? And I’m sure you get the point at the first sight reading the changes.
One thing we should note that, the way we build our Golang source (line no 6) is also getting changed. The reason is to make sure the binary is running well on alpine, we need to adjust it because it is different environment.
Well, let’s build it and see the result.
When you want to see the size….. better you prepare yourself.
Wohooo… It is 10.6MB only! ❤ ❤ ❤
And the most important thing, it is still running well as expected.
And…. IT’S DONE!
It is simple, yet applicable. At least for me, the only-256GB-SSD notebook user.
Please find the github repo for this project here.
— — —
“Thanks man! Now I am still able to enjoy my Iron Man collections anywhere directly from my local drive”
“Wait… so what about your babies photos?”
“It is safe….. on my DropBox :D”