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:
- Create a Github repo with the Dockerfile example
- Setup Github integration at Docker hub: Instructions, example
- Make sure that you name the image the same thing as what you specified in your
.gitlab-ci.yml
file - 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!