Hello everyone, today I’ll try to explain how to create multi-stage Docker builds in order to decrease build size with Dockerfile on a small Go application and the latest GoLang image from DockerHub.
Through this tutorial I won’t publish any code snippets directly, I’ll instead give you a repo to copy and paste.
First, we’ll create a really basic Go webserver using the Mux package. “Package
gorilla/mux implements a request router and dispatcher for matching incoming requests to their respective handler." from their GitHub page. You can also learn how to install that package on your local from the link.
After that, we need to create a main.go file with the following content.
After we create our main.go we can go ahead and initialize a go module with the command:
go mod init (nameselectionforappofyourchoice)
Then we can check if the server is up by running our application with the command:
go run .
Then we should quickly create a Dockerfile in same directory and the final look of our project should be like this one now.
Writing our Dockerfile is a little bit more tricky but I’ll try to explain each step.
- We pull golang image with a specific version from DockerHub.
- We create a directory for ourselves in our container.
- We copy go.sum and go.mod files to our directory from the line above.
- We download our dependencies.
- We copy everything from our current directory to our directory in the container.
- We should run go build in order to get a statically compiled go binary. (Actually, all we want to do in this tutorial is to use a statically compiled Go application and with that binary in our hands, we can run it even in a smaller Docker image like Alpine with no real ability to compile a Go application.) CGO_ENABLED=0 for static compile and -o flag indicates the output folder.
- We pull another image called Alpine from DockerHub with a smaller build size.
- We copy /bin/app folder from our older stage to /bin/app folder in new image.
- We define /bin/app as our entrypoint
We are good to go now. We can build and run our container with the following commands:
docker build -t <tagselectionofyourchoice>
docker run -p 5000:8080 <tagselectionofyourchoice>
## Opening a port from our Go app 8080 to our local port 5000.
Now our Dockerized app is up at port 5000.
Now we as we can see our container is fully functional yet the image size is significantly smaller. I will not share another picture for it but the original Golang image usually takes around 900MB of space alone. This is thanks to the static compiling abilities of Golang.
I hope that tutorial can help you. I’ll see you in the next blog posts :).