How do you set up a continuous integration and deployment pipeline using GitLab CI/CD?

Setting up a continuous integration and deployment (CI/CD) pipeline can seem daunting, especially if you’re new to the concept. However, utilizing GitLab CI/CD can streamline this process, making it straightforward and efficient. By the end of this article, you will understand how to set up a CI/CD pipeline using GitLab and have the ability to automate your build, test, and deployment processes.

Understanding the Basics of GitLab CI/CD

GitLab CI/CD is a powerful tool that enables developers to automate the process of integrating and deploying their code. By leveraging pipelines, jobs, and runners, GitLab CI/CD ensures that every change is automatically tested and deployed, fostering a seamless development workflow.

At the heart of GitLab CI/CD lies the .gitlab-ci.yml file, a configuration file where you define your pipeline’s stages, jobs, and the conditions under which they run. Each time you commit changes to your GitLab repository, the gitlab pipeline is triggered, running through the stages defined in this file.

Setting Up Your GitLab Runner

Before diving into the .gitlab-ci.yml configuration, it is crucial to set up a GitLab Runner. A runner is a lightweight, agent-like application that executes the jobs defined in your pipeline. Here’s how you can set up a GitLab Runner:

  1. Install Docker: GitLab Runners can be installed on various platforms, but using Docker simplifies the process. Start by installing Docker on your server.
    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io
    
  2. Register the Runner: Use the GitLab instance URL and registration token to register your runner.
    sudo docker run --rm -t -i -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner:latest register
    
  3. Configure the Runner: During the registration process, specify the runner’s capabilities and the executor (Docker, in this case).

By the end of this process, your GitLab Runner will be ready to execute the jobs defined in your pipeline.

Crafting the .gitlab-ci.yml File

The .gitlab-ci.yml file is where you define your pipeline’s structure. This configuration file resides at the root of your GitLab project. Here’s a basic example to get you started:

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script:
    - echo "Building the application..."
    - docker build -t myapp:latest .

test_job:
  stage: test
  script:
    - echo "Running tests..."
    - docker run myapp:latest ./run_tests.sh

deploy_job:
  stage: deploy
  script:
    - echo "Deploying the application..."
    - ssh -i /root/.ssh/id_rsa user@server 'docker pull myapp:latest && docker run -d myapp:latest'

Understanding the YAML Structure

  • Stages: Define the sequence in which jobs run. In this example, the stages are build, test, and deploy.
  • Jobs: Under each stage, you define individual jobs. Each job has a script that executes the commands.

Adding SSH Keys for Secure Deployment

To deploy your application securely, you will need to use SSH keys. Generate an SSH private key and add the public key to the authorized keys on your deployment server. Then, store the private key in a GitLab CI/CD secret variable for secure access during deployment.

ssh-keygen -t rsa -b 4096 -C "[email protected]"

In GitLab, navigate to your project settings and add the private key as a CI/CD variable.

Building and Testing Your Application

Once your .gitlab-ci.yml file is in place, every commit will trigger a new pipeline. Firstly, the pipeline will build your application using Docker:

build_job:
  stage: build
  script:
    - docker build -t myapp:latest .

After the build, the test job will run the tests against the newly built docker image:

test_job:
  stage: test
  script:
    - docker run myapp:latest ./run_tests.sh

By running tests in a containerized environment, you ensure consistency and reliability.

Deploying Your Application

Deployment is the final stage of the pipeline. Using SSH, you can securely deploy your application to a remote server. Here’s how you can set up the deployment job in your .gitlab-ci.yml file:

deploy_job:
  stage: deploy
  script:
    - ssh -i /root/.ssh/id_rsa user@server 'docker pull myapp:latest && docker run -d myapp:latest'

Ensure to disable stricthostkeychecking for seamless SSH access during deployment:

before_script:
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | tr -d 'r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts

Integrating with Docker and Container Registry

Using Docker enables you to build and deploy consistent environments. You can also leverage GitLab’s container registry to store your Docker images. This allows you to tag and version your images, ensuring traceability and reproducibility.

Tagging and Pushing Docker Images

You can enhance your pipeline by tagging your Docker images with the commit hash or a latest tag and pushing them to the container registry.

build_job:
  stage: build
  script:
    - docker build -t myapp:$CI_COMMIT_SHA .
    - docker tag myapp:$CI_COMMIT_SHA myregistry.com/myapp:latest
    - docker push myregistry.com/myapp:$CI_COMMIT_SHA
    - docker push myregistry.com/myapp:latest

By tagging your images, you manage multiple versions, facilitating rollbacks if needed.

Handling Merge Requests and Testing

GitLab CI/CD also allows you to run pipelines for merge requests, ensuring that every proposed change is tested before being merged into the main branch. To set this up, you can use the only keyword in your .gitlab-ci.yml file:

test_merge_requests:
  stage: test
  script:
    - echo "Running tests for merge request..."
    - docker run myapp:latest ./run_tests.sh
  only:
    - merge_requests

This ensures that your code is always in a deployable state, increasing the robustness of your deployment pipeline.

Implementing a CI/CD pipeline using GitLab CI/CD can significantly streamline your development and deployment processes. By setting up a GitLab Runner, crafting the .gitlab-ci.yml file, and leveraging Docker, you can automate your builds, tests, and deployments. Integrating SSH for secure deployments and managing Docker images through the container registry further enhances your pipeline’s efficiency and reliability.

By following this guide, you can create a robust and automated CI/CD pipeline, ensuring that every code change is tested and deployed seamlessly. Embrace the power of GitLab CI/CD to accelerate your development workflow starting today!