In [Part 1][1] and [Part 2][2] we built a functional API using Golang and MongoDB, although as it stands its insecure. We can add password protection using Basic Auth while deploying ([See here][3]). In this tutorial we will build a very tiny docker container and deploy to our Kubernetes Cluster.

For the purposes of this tutorial I won’t be showing you how to setup a Kubernetes Cluster, However you can do it easily with [Terraform][4] and [DigitalOcean][5].

Assumptions Made

  • You have a functional Kubernetes Cluster
    • GKE – Google Kubernetes Engine
    • AKE – Azure Kubernetes Engine
    • EKS – Elastic Kubernetes Engine (AWS)
    • Rolled your own
  • You have a working [nginx ingress][6] controller
  • You have a working loadbalancer for your cluster
  • You have Docker running on your machine
  • You have a dockerhub account

Accepting Environment Variables

As we will be deploying this to a cluster with an external MongoDB instance we need to accept an environment variable for MongoDB.

in our main.go file replace

var session, _ = mgo.Dial("127.0.0.1")

with

1
var session, _ = mgo.Dial(os.Getenv("MONGO_HOST"))

Remember to add the os import

Building our Container

Compiling the Binary

As I mentioned we will be building a very minimal docker container for our API. This is acomplished by building our go binary using CGO and GOOS environment variables. This will build a statically linked binary for the GOOS we choose, For this scenario it will be Linux.

So in our project directory lets build our binary. To make it easier and repeatable I have created a Makefile

1
2
all: main.go
 CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o bin/todo-api .

now run make and you will have an ELF binary in bin/todo-api

You can run this however it will fail to connect unless you specify a valid MongoDB host using the MONGO_HOST environment variable.

Building the Container

In order to make our container as small as possible we will be using the scratch base image from Docker. This image literally has nothing in it, This will allow us to add our binary and nothing else. So lets write our Dockerfile

1
2
3
4
5
6
7
8
9
FROM scratch

LABEL authors="Keiran Smith <opensource@keiran.scot>"

ADD bin/todo-api todo-api

EXPOSE 8000

CMD ["/todo-api"]

Now we have the Dockerfile we can run

$ docker build -t affixxx/todo-api:latest .

remember to tag it with your own dockerhub username!

And thats it we now have a super small Docker container mine is 7.52MB

You can run it but remember to specify the MONGO_HOST environment variable.

Lets push to dockerhub

$ docker push affixxx/todo-api

And thats all there is to it. We can now look at deploying our application. Feel free to [deploy mine][7]

Deploying to Kubernetes

Before we start I recommend we create a namespace for our project.

Having our project in a seperate namespace ensures that we won’t affect anything else on our kubernetes cluster.

Deploying MongoDB

Our MongoDB deployment has 2 parts, A Service and a Deployment. Setting up Persistent Volumes is beyond scope and I will write a tutorial in the future on working with PVs in kubernetes.