Before getting in to more details and seeing the strategies we can use to set up a CI/CD pipeline in Gitlab using gitlab runner, let’s first see some details and points about Continuous Integration and Continuous Delivery (CI/CD).
What is continuous integration ?
In short terms it is the process of merging together all new codes by programmers.This merging together is usually in a shared repository. But the process can be further advanced by adding test scripts and running other scripts like building production apps.
What is continuous delivery ?
Continuous delivery states that applications can be automatically deployed on a server. The servers can be either production or staging. This usually happens when a new code or feature is pushed to the repository.
Why Is CI/CD Important ?
Let’s list some points down below to show the importance CI/CD in our application development process
- Consistency: CI/CD gives us consistency in the overall development life cycle by giving us a specific automated testing and building process.
- Error Reduction: CI/CD can reduce the errors that can be caused by developers in doing manual deployment and tests.
- More time spent on actual development : It will reduce the time and energy that will be put in to place to do manual deployments. .This way we can put our resources in actual coding or testing.
- Happy Developers : Running the same command every time you make a change can some times be boring. By automating our deployment we can reduce repetitive tasks and make releases more appealing.
Integrating CI/CD with gitlab to your existing application
When it comes to CI/CD there could be multiple service providers, but we chose to implement our CI/CD with gitlab in the ease of use it provides and also the lower learning curve that comes with it. And I have to admit using the same service provider for handling you code repository and your CI/CD feels consistent and reliable.
In the tutorial below we will see how we can add a CI/CD pipeline to an existing application running on docker and NodeJS. We will then deploy the application to a server running Ubuntu 18.04 . Here is an example of an existing code base running on docker, NodeJs, Express and Mongoose boilerplate. Check out this post on some basic of docker if you are unfamiliar.
The important thing to note here is CI/CD is not limited to only Node.Js applications, you can pretty much use it in any programming language or framework. Once you are up an running you will be able to run any command on your server to either install packages, build your application and run your application.
The First thing you need is a server where you can SSH in to and run commands this can either be a VPS or your own dedicated server. In our case a VPS running Ubuntu 18.04.
Install GitLab runner
GitLab runner is the program that will receive changes from your repository, run your commands from .gitlab-ci.yml file. It then send back the results of your commands back to GitLab. You can read more about it from the official documentation.
Add the official GitLab runner repository
Run the command below that will retrieve gitlab’s official bash script to add gitlab runner repository to your system based on your architecture.
$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
Next run the apt install command to install gitlab runner on your system.
$ sudo apt-get install gitlab-runner
After that command runs successfully your system will now be able to run gitlab-runner commands. Run the next command to make sure gitlab runner is installed in and view some description about our installation.
$ gitlab-runner -v
Register the gitlab runner next. This will integrate your gitlab runner with your repository on gitlab.
$ sudo gitlab-runner register
After running the register command you will be prompted to fill out some information regarding your repository and some other information. The prompts in chronological order are listed below
- The gitlab-ci coordinate URL. You can find it in GitLab repository – -> Settings –> CI/CD –> Runner Page.
- The gitlab-ci token. This information is also found in the setting of your CI/CD just like the gitlab-ci coordinate URL,
- The gitlab-ci description. You can write some description about this specific runner here.
- The gitlab-ci tags. Pay attention to the tag you write here gitlab will be matching which step to use based on this. It cab be something like myapp-production . You will be using this tag later on when we write the ,gitlab-ci.yml configuration file.
- Finally the executor. Use shell executor here as we are going to be running shell commands from our configuration file.
The next thing we need to do is to make sure our gitlab-runner user will be able to run sudo commands with out entering a password. Out gitlab-runner user is created during installation so there is no further configuration needed to add the user. Open your sudoers file using nano terminal editor.
$ sudo nano /etc/sudoers
Add the line below to the end of the file which specify that no password is will be required for the sudo user. And finally save the file.
gitlab-runner ALL=(ALL) NOPASSWD: ALL
This will conclude the configuration needed to set up gitla-runner on your server. Next we will see how we can write a configuration file in our repository, This file will communicate with our gitlab-runner and tell it which commands to run,
Adding .gitlab-ci.ym file
The gitlab-ci.yml file is a configuration file which gitlab will determine the structure of our pipeline and the commands the gitlab-runner will execute. We can also specify what decisions to make when a certain condition happens like when a process succeeds or fails. Below is a simple example of a .gitlab-ci.yml file. The commands will consist of running a dockerized Node.JS application with the help of docker-compose. Make sure to install both docker and docker-compose to your server if you are using this stack.
image: docker:latest services: - docker:dind # List stages in the pipeline, you can add other steps like test here stages: - deploy step-deploy-production: stage: deploy before_script: - export DYNAMIC_ENV_VAR=PRODUCTION only: - master tags: - myapp-production # The tag you used when registering gitlab-runner script: - echo setting up env $DYNAMIC_ENV_VAR - sudo docker image prune -f - sudo docker-compose down - sudo docker-compose build --no-cache - sudo docker-compose up -d
This simple file contains the minimal configuration needed to deploy a simple dockerized application. The most important parts are stages block, the only block and the script block.
In the stages block we list out the stages our pipeline will have. In the case of this example we only have a deploy stage but you can also add other stages like test and build to your pipeline.In the step-deploy-production block on line 10 we configure our deployment step, like telling the runner only to run this step on master branch on line 14, which tag to use to map to our gitlab-runner on line 16 and what scripts to run on our server on line 18.
After pushing this file to your repository your gitlab-runner will automatically start executing commands on your server to deploy your application. In the case of our example above the gitlab runner will start only when there is a push or merge to our master branch. You can view the status of your pipeline in Gitlab Repositor –> CI/CD –> Pipeline then select the pipeline you are interested in whether it is running, successfull or failed.
You can read more about .gitlab-ci.yml configuration file from the official documentation here.
Finally make changes, commit and start pushing features to your repository and your server !!