Multistage dockerisation of a Golang application

Hi there!!

In this post I will like to share a little dockerisation technique for clean deployment of application in docker. This application is essentially a demo application app I wrote for another tutorial of mine where I needed a working application to deploy into AWS ECS. I decided to release it hoping that it could be useful to someone. Anybody can use it to start with their APIs in Golang journey.

We are not following the typical Golang project structure as we essentially have a single main.go file. So that would be an overkill.

Let’s create our working folder mkdir -p ~/RandomWorkspace/mcp-golang-apidemo

In the mcp-golang-apidemo folder please initiate your go module. I will be using github.com/kdjomeda namespace. Feel free to use whichever you are comfortable with. We will pull the libraries that we need at the same time. We are making use of the gorilla toolkit and off the toolkit, we are using the handlers library, which is a collection of useful middlewares. We are also making use of the mux library as well which we will use as our http router.

Because this application itself is a sort of shell application that simulates apis in golang, it’s rather small and holds in one single file. I will therefore paste the content of the file and follow it with some explanation on choices made inside it.

Main Application

the healthcheck function is as its name indicates helps with healthcheck. It’s a simple function that returns the current date and http status 200 to be use as health check.

The cityHandler simulates the processing of an http POST request . A request payload via post is sent to the app as if a resource will be created by that. It then replies with an http status 201 confirming creation of the resource. The city struct holds the post data. It has fields such as Name and Population. The Name being the name of the city and the Population the demography of the city.

The main function wires everything together. It registers the paths and the methods that handles them. It also defines how the Golang built-in server is configured. It’s important to mention here that I choose not to hardcode the port of the server as seen in multiple sites online. Instead I pass it to the application as an environment variable. We need to also highlight the fact that we are using the loggingHandler middleware of gorilla toolkit. It writes to the standard output of the container all logs used in the app.

Dockerisation

We will need to jump in to the dockerisation now. Before we do that we need to define our dockerignore file to prevent unwanted files to find its ways into the image. Find below the content of the .dockerignore file.

We will move now to the dockefile as depicted below

In this docker file at line 5-8, similarly to nodejs’ package.json, we move the go.mod and go.sum first followed by go mod download. This helps with caching as those files only change when we add new libraries or dependencies.

The line 10 copies all the go file in the folder and line 12 builds it as apidemo binary.

Line 16 marks the beginning of the second stage of the dockerfile. The stage where we make use of the previous stage. We first create a non root user gouser as it’s always a good practice to stay away from root users, either in docker or regular VM.

Line 22 copies the binary from the builder stage into the deploy stage. On line 24 we use the created user and execute the binary at the entrypoint.

Build and Execution

In this section we will build our docker image and run it. If successful we will test with some curl requests. Before you execute the docker build command, make sure you are in the same folder as the dockefile.

In the command above we are building and running the docker image/container. The -e is passing the PORT environment so that application can use that to start the application with. We are also doing a mapping of our local port 9090 to the docker container port 9099(which is from the PORT env var)

Let’s launch a different terminal to send some requests to the application.

The output should be something similar to the following

That’s all for this one. I hope I have been able to show how to use multistage dockerisation of an application. Beside the dockerisation, I also hoping this article will be useful of anyone beginning a journey in golang. Finally the article also tries to link few good practices together . Practice such as avoiding using root user , hard code port number, prevent files from being copied into the image by excluding them in the dockerignore file.

Leave a Reply

Your email address will not be published. Required fields are marked *

captcha * Time limit is exhausted. Please reload the CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to top