Building your CI-CD flow with gitlab-CI and docker

Andy Chang
4 min readMar 19, 2021

Struggling from manually packaging modules for product

Currently my team has started to construct a CI-CD flow due to the constantly product released. We decided to use gitlab-ci to help us through the hell from manually release the product by collecting the code from each service(module).

First of all, sign up in gitlab or you can turn left to avoid this article. OK, now you have an account, congratulations! Let’s talk about how to build a complete flow for CI-CD! CI-CD is a abbreviation of “Continuous Integration and Continuous Delivery(or Deployment)”. It is very intuitive from its literal meaning. The developer can keep uploading codes, the CI-CD flow helps integrating the uploaded codes and makes sure the quality by unit test and integration test. Finally the uploaded codes will be merged into the product and the product will delivery to a machine automatically. The most important thing in the whole flow is, how could you make sure the build environment consistency? Docker is a very powerful package that it can build a virtual machine so fast and effortless.

Why gitlab-CI?

But why we need gitlab-CI? We could just run the script in the docker environment, why we need it? Here’s my perspectives.

  1. Build machine — Normally, your script will run on a certain machine for CICD. Gitlab allows you register a gitlab runner on target machine with a generated token. You don’t have to bother from doing authorized to build machine in the script.
  2. Trigger mechanism — You could define the timing in gitlab-ci.yml to tell gitlab when should trigger the CICD.
  3. Maintainable and debuggable — Every message will be saved and displayed on the gitlab. Also you will find out where is the error happened.
  4. Build script is easy to write and very readable — Developer can realize the flow from the script easily.

Environment setup

  • Installing gitlab-runner on your build machine, you could follow the tips from this link.
  • register target machine as a gitlab runner

reset runner registration token

sudo gitlab-runner register on target machine

specify gitlab url and token id for the registration

specify docker as executor

sudo vim /etc/gitlab-runner/config.toml
[[runners]]
name = "spring1"
url = "<http://gitlab.com/ci>"
token = "337a267a26c1d8c6f5b2a37a26"
executor = "docker"
[runners.docker]
tls_verify = false
image = "spring"
privileged = true // specify privileged rights to container for mounting repositories through samba
disable_cache = false
volumes = ["/cache"]
pull_policy = "if-not-present" // gitlab will find the exist image in local if the image is not found from internet
[runners.cache]
  • install docker
  • docker pull <any_online_image>
  • create a container with image specified
  • docker create — name <container_name> <image_id>
  • After the container is created, check the container list by typing the following commands.
  • docker ps to check running containers
  • docker ps -a to check all containers
  • docker start <container_id> to start the container, recreating a container if the container isn’t running. If the container can’t start eventually, run docker run -it <image_id> bash to access the environment without pre-creating a container. It will create a non-running container, type docker ps -a to get the <container_id>.
  • docker exec -it <container_id> bash to enter the virtual environment(image) you have set up.
  • Type exit to quit from the environment.
  • docker export <container_id> > <custom_name>.tar to export environment
  • cat custom_name.tar | docker import — custom_name:1.0.0
  • docker images to check if the image is exist

Write your .gitlab-ci.yml file

The file basically define your build environment and build flow. Here is some property I used in the file.

image — Using the docker image on the build machine as your pure virtual environment to ensure that the CI-CD always runs on the same environment.

stages — Normally has test phase, build phase and deploy phase. Defined on the top of the nested structure.

stages:
- test
- build
- deploy

cache — Every stage is independent from each, they are working on the common environment but not sharing the resources generated in the stage. But sometimes the packages could applied to every stage and you don’t have install them every time, you can use the cache then. By the way, it’s placed on the top of the nested structure.

cache:
paths:
- node_modules/

script — Basically it contains the logic of whole flow.

tags — Specify a registered runner from your gitlab url.

only — To tell gitlab when will CI-CD triggered. CI-CD will be triggered every git push if this property has not set.

This is my very first time to post a article on the internet. I know I have lots of grammar error and very lack of vocabulary, I want to be a good speaker and writer in English though. If I have any wrong in this article or you are confused with part of the article. Please let me know!! We could discuss anything about programming! Very appreciate you!

--

--

Andy Chang

一點一滴進步的軟體工程師,努力讓今天的自己比昨天的更好