AL

View Original

Developing with Golang with Docker

During some of my adventures learning Go, I’ve found it very cumbersome to be installing dependencies, working on different workspaces, integrating my go projects with different build systems (whether enterprise, or building my own), using some of Go’s best practices.

First of all:

Prerequisite

  • Docker - Seriously just docker, you don’t even need Go installed on your host.

Why Use Makefiles?

I remember during college that Makefiles were really useful at building the thing, running the thing, testing the thing, and cleaning up the thing for my C/C++ projects. I figured instead of using go build all the time, and having a script to deploy to linux, mac, or windows, I can do it all in a Makefile.

To get a feel of what my typical workspace is like, see below:

├── MyApp
├── bin
├── src
│   ├── MyAppExecution
│   │   ├── main.go
│   ├── Private
│   │   ├── privateExecutions.go
│   └── Gopkg.toml
├── .gitignore
├── Jenkinsfile
├── README.md
├── Makefile
├── build-go-binaries.bash

Some Code

One of the things that really irks me with a lot of examples online is that even with Makefiles, I still have to worry about go dependencies on the host, I still have to assume whatever build system that I am using has go installed, and I have to assume that these build systems have access to the internet or not.

Before we move to our Makefile, let’s get some house keeping done first. Let’s just write a super bare bone Golang application that imports a nice logger library, and have it print Hello World.

├── makefile_example
├── src
│   ├── makefile_example
│   │   ├── main.go
│   ├── Gopkg.toml
├── Makefile
├── Dockerfile

In main.go, I have the following code:

See this content in the original post

In Gopkg.toml, I have the following configuration:

See this content in the original post

Nothing too special, but this will enforce two things for this article:

  1. Using external libraries

  2. Setting up our project to be built using Makefiles

Note: Even though I did say all you need is Docker, you could (or maybe should) have Go installed on your development environment to do your quick testing and local development. Having to use docker all the time does require more time, despite it’s benefits.

Dockerfile

We’ll now need to write a Dockerfile to build our docker image.

See this content in the original post

Basically a rough summary of what this does is:

  1. Installs a tiny golang image

  2. Updates and installs packages

  3. Sets the bin directory for the go binary

  4. Adds everything in your directory to the working directory

  5. Gathers dependencies

  6. Sets the working directory

To test this, you can run sudo docker build . to create your docker image. Below is a sample execution of my docker build:

See this content in the original post

Finally, the Makefile

Build the thing

Let’s just start with a bare bone makefile that will just build the thing.

See this content in the original post

Cool! Now we can just run make or make build, and our code will now build our go code.

Run the thing

But what about actually running our code? We can simply add a run rule, and tell it to run that file

See this content in the original post

And now, when you run make run, you get something like:

See this content in the original post

Nice! I would also add a rule to prevent building, if you just want to run the same image:

See this content in the original post

Compile the thing!

Finally, we’ll want a way to compile our executable to any operating system. Thankfully, we have an awesome developer over at https://www.digitalocean.com/community/tutorials/how-to-build-go-executables-for-multiple-platforms-on-ubuntu-16-04 to help us.

I’m going to have a slightly modified version (changing the destination OS from windows to linux , and moved the binaries to the bin/ directory) below:

See this content in the original post

Save this file as build-go-binaries.bash in your top level workspace. Now let’s modify our Makefile to add a compile rule.

See this content in the original post

make compile will run build, and then compile the binaries

See this content in the original post

Now we can run the binary, since we mounted the bin/ folder to our compilation command.

See this content in the original post

We can even run this on our linux box!

See this content in the original post

Congratulations! Hopefully you reached to the end of this and found this article useful!