Testing Go projects with Docker

Our CI server is getting a bit overloaded, and I didn’t want to install more packages on it to test our new go projects. Since we are also playing a lot with Docker lately, it felt natural to use it to run test suites and determine coverage of go projects. Just by installing docker on our private CI server, all our team is now able to add various projects, with different versions, without interfering with other projects or environments.

This first step was to define a common Go base image for our go projects :

# Prefer debian over ubuntu
FROM debian:wheezy
# Let's install go just like Docker (from source).
RUN apt-get update -q
RUN apt-get install -qy build-essential curl git mercurial bzr
RUN curl -s https://go.googlecode.com/files/go1.2.src.tar.gz | tar -v -C /usr/local -xz
RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
ENV PATH /usr/local/go/bin:/go/bin:$PATH
ENV GOPATH /go
# we're using godep to save / restore dependancies
RUN go get github.com/kr/godep
# Cover is used in almost all projects too
RUN go get code.google.com/p/go.tools/cmd/cover
WORKDIR /go

Let’s create a Makefile along to this Dockerfile:

all: build

build:
        docker build -no-cache -rm -t docker:5000/go:1.2 .

run:
        docker run -rm docker:5000/go:1.2

We can argue on the no-cache parameter here, but since the second line is a “apt-get update”, we should not cache this. If we decide to modify th Dockerfile later, and add a new debian package with “apt-get install”, it will possibly fail because it won’t be available anymore for download.

Anyway, we now have our docker:5000/go:1.2 image ready to be used. We won’t use this image directly, but instead share it in other docker images.

Let’s Create our go project

Let’s create a new “go-example” project on our git server. The local path in $GOPATH will be something like “$GOPATH/src/gitlab.local/tech-angels/go-example”. Let’s create a Dockerfile for this project:

FROM docker:5000/go:1.2

ADD . /go/src/gitlab.local/tech-angels/go-example
# Fetch deps
WORKDIR /go/src/gitlab.local/tech-angels/go-example
RUN go get
# Allow to mount the current version in the container
VOLUME /go/src/gitlab.local/tech-angels/go-example

With the common Makefile:

all: build

build:
        docker build -no-cache -rm -t docker:5000/go-example .

We now have a full project environment, ready to compile and test, without installing anything else than Docker.

And now, configure the CI Server

We are using Gitlab-CI to test our projects, but the following will work with any CI server out there.

docker pull docker:5000/go-example
docker run -t -i -rm -v `pwd`:/go/src/gitlab.local/tech-angels/go-example docker:5000/go-example go test -cover

and Voilà!

Our CI will just start a container, run the tests, and get an exit code from the go command.

Go further

We didn’t add the save / restore deps step in this very simple example. It’s trivial to add it, and you’ll need a test script inside the container for that.

Also, you probably realize now how simple it is to test with different go versions!


blog comments powered by Disqus