By Viktor Eriksson

Continuous Integration with Gitlab CI and Docker

Setting up Gitlab CI to test pushed builds

At Pilloxa we strongly believe in setting up a good continuous integration flow so that deploys can be as automated as possible while giving the developers the confidence that a good test suit brings.

This post will give an overview of how one may setup a simple yet effective CI system leveraging Gitlab CI and Docker. The example will use a Clojurescript project.

Disclaimer: I’m no pro at Docker nor Gitlab CI, so there is likely some things I’ve done suboptimally. Send any suggested improvements to viktor@pilloxa.com

Prerequisites

  • A Gitlab repo
  • A test suite that will be tested on each build

Step 1: Select or create Dockerimage

Gitlab CI uses Dockerimages that it runs the tests in. For those not too familiar with Docker it means that you can run your tests in a preconfigured linux image. In my example I used an image that had everything necessary for my project installed (Clojure and NodeJS). The advantages of using a Dockerimage for running your tests are:

  • Speed: The test suit doesn’t have to install a bunch of stuff before it runs (as it would have to in TravisCI for example)
  • Reproducibility: The test suit can be run in the exact same environment locally as on the server, differences in developer machines will no longer matter

You have two options, you can select an already available Dockerimage from Docker hub or create your own Dockerfile and build an image from it.

We are using Clojurescript with NodeJS as the testdriver. I therefore extended the official clojure:lein-2.6.1-alpine image with NodeJS as per the following:

FROM clojure:lein-2.6.1-alpine
MAINTAINER Viktor Eriksson <myemail>
RUN apk add --update nodejs

More instructions on how to create a Dockerfile

_Note: alpine means that it is a slimmer version of linux used, clojure:lein-2.6.1-alpine weighs 173 MB compared to the 658 MB of the normal clojure:lein-2.6.1 _

Step 2: Create account at Docker hub

Docker hub is Docker’s official repo for Dockerimages. That is where Dockerimages are downloaded from when you run Docker locally or when Gitlab CI runs it for you.

To upload images you naturally need to register an account.

Step 3: Install Docker

Naturally you will need Docker to use Docker. See instructions here.

Step 4: Test your Dockerimage locally

When you are done with your Dockerfile and Docker is installed you can build the image locally with

docker build -t your-dockerhub-id/your-dockerimage-name .

Step 5: Install gitlab-ci-multi-runner

Gitlab CI works with a .gitlab-ci.yml file, quite similar to .travis.yml. In that file you setup the instructions for the tests. This file can also do other magic CI stuff but that is not covered in this post.

To emulate the Gitlab CI setup locally and test the gitlab-ci.yml file you will need gitlab-ci-multi-runner, install instructions here.

For macOS:

brew install gitlab-ci-multi-runner

Step 6: Write your .gitlab-ci.yml file

Since the language and environment specific things were already installed in my Dockerimage in Step 1 I now only have to setup my project. My .gitlab-ci.yml file hence looks like this:

# .gitlab-ci.yml
image: vikeri/clojure-node
before_script:
  - lein deps
  - npm install
test:
  script:
    - lein doo once

Step 7: Test your CI Setup Locally

Now you can test the Dockerfile and the .gitlab-ci.yml file locally to make sure that things run as they should (fat chance on first try).

You have to commit your changes to your code (adding the .gitlab-ci.yml for example). Then run the following in that directory:

gitlab-ci-multi-runner exec docker test

If everything is setup correctly the tests will run and you will get the very satisfying Build succeeded in the end.

Step 8: Add your image to Docker hub (if you created your own Dockerfile)

If you only used an already available Dockerimage, you can skip this step.

If you created your own Dockerfile you have to upload it to Docker hub so that Gitlab CI and others can download it. There are two options: Push it directly or Auto build from Github

Auto build from Github

A neat thing is that if you have a Dockerfile that is not confidential you can add it to a Github repo and then whenever you push changes to that repo the image on Docker hub will be automatically rebuilt. To do this, do the following:

  1. Create a Github repo with the Dockerfile example
  2. Setup Github integration at Docker hub: Instructions, example
  3. Make sure that you name the image the same thing as what you specified in your .gitlab-ci.yml file
  4. To trigger the first build (if your Dockerfile was already in the repo), go into Build Settings and then click Trigger.

Push directly

If you are not too keen on the whole Github thing you may also use the following command:

docker push your-dockerhub-id/your-dockerimage-name

Step 9: Push your code to Gitlab and profit

Push the code to Gitlab and then go into the Pipelines tab on your repo. If everything is as it should you should see a build in process and then eventually the gratifying passed tag.

Interested in using tech to save lives? We’re hiring!