March 6, 2019

GitLab Continuous Integration with Docker

Automate your testing, build process, integration, and deployment of your applications with GitLab.

GitLab Continuous Integration with Docker

When writing the NodeJS logging post (read it here), I had to continuously move my code to my server or make the needed edits directly on my web server. This became monotonous very quickly. As such, I decided to look at GitLab's CI/CD feature to automate this task. In this post, we will look at how to automate the build and deployment process of a Docker application.

GitLab's CI/CD can be found here for your reference.


How is works

CI/CD allows you to automate tasks after every commit. After you have set everything up, Gitlab will create pipelines, which will execute the jobs you have outlined to run. The tasks are ran against what is called a runner. You have the option to use GitLab's runners or a custom runner you have setup on your server. The most common tasks you will see CI/CD used for are automating your tests, builds, and deployment to either staging or production.

The below image comes from the GitLab documentation, and gives a visual of the CI/CD workflow.

GitLab CI/CD Design

Create your CI/CD Configuration

The first thing we are going to do is define the jobs you want to execute. Create a new file named .gitlab-ci.yml in your project folder, and add the following.

stages:
  - build
  - deploy

build_image:
  stage: build
  script:
    - docker build -t test .
  artifacts:
    paths:
      - node_modules/

start_image:
  stage: deploy
  script:
    - docker stop test || true && docker rm test || true
    - docker run -d -e NODE_ENV='production' -p 9002:9002 -v /tmp/logs:/usr/src/app/logs --name test test:latest

Let's look at what we are doing here.

  • The stages section defines the different stages of your CI/CD. We are creating a build and deploy stage.
  • We create a new section, which will be used as our pipeline name. build_image is part of our build stage, and will build our docker image for us.
  • The deploy section takes our docker image and starts it on our server.
  • I am using a trick to ensure the docker image is stopped and removed before trying to start it. The command needs to execute without error for the pipeline to succeed.

Setting up your runner

Lets now setup our runner. We'll start by going into our repository on GitLab and navigating to the CI/CD settings. Next, select to expand the Runners sections. This will bring you to a page that looks like this

Disable Shared Runners

The first thing to do is disabled shared runners. We do this because we want our pipeline to execute on our servers only. Leave this page open, as we will need it in a few minutes.

Now, login to your remote server, and install the gitlab-runner application. If you server is running Ubuntu, RHEL, CentOS, or Mint, you can follow these instructions. All other platforms can use these steps.

After you have installed gitlab-runner, lets create our own runner.

sudo gitlab-runner register -n \
--url https://gitlab.com \
--registration-token 1Gis_dvV-thAe7pRZz6f \
--executor shell \
--description "blog test"
Runtime platform arch=amd64 os=linux pid=13681 revision=8bb608ff version=11.7.0
Running in system-mode.

Registering runner... succeeded runner=1Gis_dvV
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Lets breakdown this command.

parameter description
--url gitlabs url
--registration-token This is your runner token, which you get from the same page above. This links your runner to your repository
--executor This tells gitlab how to execute the commands in your gitlab-cli.yml file
--description This gives your runner a name, which will be displayed on your gitlab GUI as well as on your server

One thing to note is that we are using a standard shell as our executor. The gitlab-runner does have the ability to set this to docker, but in this case we are putting all of our docker commands inside our gitlab-cli.yml file.


Summary

We have successfully deployed GitLab's CI/CD into our project. Now, every time you push changes to to your GitLab repo, it will automatically build and run our docker image. You no longer need to push your source code, login to your server, and manually build and deploy your container.

We are barely touching the capabilities of the CI/CD features inside GitLab. Some features that I am looking forward to testing out are the ability to run my unit and functional testing automatically after every push as well as the ability only run CI/CD on certain branches.

Hope this post was helpful. As always, looking forward to your comments below.