YouTube App Deployment with GitLab CI/CD

YouTube App Deployment with GitLab CI/CD

·

10 min read

In today’s software development landscape, speed and reliability are paramount. Continuous Integration and Continuous Deployment (CI/CD) pipelines can automate and streamline your development and deployment processes. This guide will show you how to create a complete CI/CD pipeline for a React YouTube app clone using GitLab.

Step 1: Create an API key for Youtube.

Step 2: Create a Repository and push it to GitLab.

Step 3: Terraform using Launch an Ec2 instance and run Sonarqube on it.

Step 4A: Create a .gitlab-ci.yml File.

Step 4B: Add the required variables for the project.

Step 5: Install Gitlab Runner on Ec2.

Step 6: Run the Application on the Docker container.

Step 7: Access the Application on Browser.

Step 1: Create an API key from Rapid API

Open a new tab in the browser and search for rapidapi.com

Account is created

Now in the search bar search for YouTube and select YouTube v2

Copy API and save it for further use at the docker stage.

docker build — build-arg REACT_APP_RAPID_API_KEY=<API-KEY> -t ${imageName} .

Step 2: Create a Repository and push it to GitLab

Go to GitLab.com and login to your account

Click on New Project

Click on Create Blank Project

Click on Create Blank Project

Provide a name for the Project

Keep Visibility to the public

Uncheck the Readme and create the Project.

Use the below commands to push code to GitLab

Files pushed to GitLab

Step 3: Terraform using AWS Provider Launch an Ec2 instance and run Sonarqube on it.

Create Terraform Main.tf

Choose an AMI: Select an Ubuntu image.

Choose an Instance Type: Pick “t2.medium.”

Key Pair: Choose an existing key pair or create a new one.

Configure Security Group:

Create a new security group. Add rules for HTTP, and HTTPS, and open all ports for learning purposes.

output IP address

# ec2 creating
resource "aws_instance" "Docker_server" {
  ami           = "ami-0287a05f0ef0e9d9a"
  instance_type = "t2.medium"
  key_name = "ci-cd"
  subnet_id = aws_subnet.Public.id
  vpc_security_group_ids = [ aws_security_group.Devops-sg.id ]
  user_data = templatefile("./install.sh",{})
  associate_public_ip_address = "true"
  tags = {
    Name = "Docker-server-"
  }
}
# security Gp
resource "aws_security_group" "Devops-sg" {
  name        = "Devops-sg"
  description = "Allow TLS inbound traffic"
  vpc_id = aws_vpc.Devops_vpc.id                 
  ingress = [
    for port in [22, 80, 443, 8080, 9000,8081] : {
      description      = "inbound rules"
      from_port        = port
      to_port          = port
      protocol         = "tcp"
      cidr_blocks      = ["0.0.0.0/0"]
      ipv6_cidr_blocks = []
      prefix_list_ids  = []
      security_groups  = []
      self             = false
    }
  ]

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "Docker"
  }
}
#output ip 
  output "ec2_global_ips" {
  value = ["${aws_instance.Docker_server.*.public_ip}"]
}

Create Provider. tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }

  required_version = ">= 1.2.0"
}

provider "aws" {
  region  = "ap-south-1"
}

Create Network file VPC.tf

#create Test vpc
resource "aws_vpc" "Devops_vpc" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "Devops-Vpc"
  }
}
#create Public subnet
resource "aws_subnet" "Public" {
  availability_zone = "ap-south-1a"
  vpc_id            = aws_vpc.Devops_vpc.id
  cidr_block        = "10.0.2.0/24"

  tags = {
    Name = "Public-subnet"
  }

}
#create Private subnet
resource "aws_subnet" "Private" {
  availability_zone = "ap-south-1b"
  vpc_id            = aws_vpc.Devops_vpc.id
  cidr_block        = "10.0.1.0/24"

  tags = {
    Name = "Private-subnet"
  }

}
#create Route Table private 
resource "aws_route_table" "Pri_R" {
  vpc_id = aws_vpc.Devops_vpc.id

  tags = {
    Name = "Private Route table "
  }

}
#create Route Table public 
resource "aws_route_table" "Pub_R" {
  vpc_id = aws_vpc.Devops_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.IGW.id
  }
  tags = {
    Name = "Public Route table "
  }

}
#Private Route table subnet associastions
resource "aws_route_table_association" "RT_A_Pri-sub" {
  subnet_id      = aws_subnet.Private.id
  route_table_id = aws_route_table.Pri_R.id
}
#Public Route table subnet associastions
resource "aws_route_table_association" "RT_A_Pub-sub" {
  subnet_id      = aws_subnet.Public.id
  route_table_id = aws_route_table.Pub_R.id
}
#create internet gateway
resource "aws_internet_gateway" "IGW" {
  vpc_id = aws_vpc.Devops_vpc.id # attach vpc

  tags = {
    Name = "IGW"
  }
}

Create User Data File $install. sh

This will install Docker and Sonarqube

#! /bin/bash

#install docker
sudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker ubuntu  
newgrp docker
sudo chmod 777 /var/run/docker.sock
#sonarqube
docker run -d --name sonar -p 9000:9000 sonarqube:lts-community

Terraform commands to provision

terraform init
terraform validate
terraform plan
terraform apply

Now copy the IP address of the ec2 instance

<ec2-public-ip:9000>

Enter username and password, click on login and change password

username admin
password admin

Update New password, This is Sonar Dashboard.

Step 4A: Create a .gitlab-ci.yml File.

Now go to GitLab click on ‘+’ and click on Newfile

File name .gitlab-ci.yml

Content

stages:
    - npm

Install dependecy:
    stage: npm    
    image:
        name: node:16
    script:
        - npm install

Commit the changes and it will automatically start the build

Now click on Build and Pipelines

Now click on Running.

You will build output

Now add the Sonarqube stage to the pipeline

Go to the Sonarqube dashboard and click on Manually.

Provide the name of the Project and click on Setup

Select the CI tool as GitLab CI

Select Other because we are using the JS App

It will provide code and we need to create a file inside our repo

Go to Gitlab and click on + and Newfile

Filename is sonar-project.properties

Paste the content that you got from Sonarqube

The file looks like this and click on commit changes

Go to Sonarqube and click on continue

Now it will provide Variables to add to our GitLab

Step 4B: Add the required variables for the project.

Variables Generated

Now go to GitLab

Click on settings and CI/CD

Click on Add variable

Now go back to Sonarqube and copy the Key

Click on Generate a token

Again Click on Generate

Now come back to GitLab and add them like the below image and click on add variable.

Sonar token is added

Now go to the Sonarqube Dashboard again

Let’s add another variable, copy them

Now go to GitLab and click on Add variable

Add the copied values like the below image

Two variables were added.

Now go back to the Sonarqube Dashboard

Click on continue

It will provide and CI configuration file copy it and use it inside our .gitlab-ci.yml file

Now go back to GitLab and edit the .gitlab-ci.yml file

Full file (update with your content)

stages:
    - npm
    - sonar
    - trivy file scan

Install dependecy:
    stage: npm    
    image:
        name: node:16
    script:
        - npm install    

sonarqube-check:
  stage: sonar
  image: 
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
    GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script: 
    - sonar-scanner
  allow_failure: true
  only:
    - main

Trivy file scan:
  stage: trivy file scan
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  script:
    - trivy fs .

Commit changes and go to pipeline stages

Now click on Sonarqube-check

output

Click on the Trivy file scan

output

Add the Docker build and push stage

Before that Add docker credentials to GitLab Variables as secrets.

Go to the docker hub and create a Personal Access token

Click on your profile name and Account Settings

Now click on Security → New Access Token

Provide a name → Generate

Now copy the token and keep it safe

Now go back to Gitlab

Click on settings and CI/CD Add Variable

Use your DockerHub username in value and Add variable

Key DOCKER_USERNAME

Key DOCKER_PASSWORD

For value use the Generated Personal Access token and add a variable.

Variables added.

Now add the below stage to the Configuration .gitlab-ci.yml file

Added Docker and Trivy image scan stages

stages:
    - npm
    - sonar
    - trivy file scan
    - docker
    - trivy image scan

Install dependecy:
    stage: npm    
    image:
        name: node:16
    script:
        - npm install    

sonarqube-check:
  stage: sonar
  image: 
    name: sonarsource/sonar-scanner-cli:latest
    entrypoint: [""]
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
    GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script: 
    - sonar-scanner
  allow_failure: true
  only:
    - main

Trivy file scan:
  stage: trivy file scan
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  script:
    - trivy fs . 

Docker build and push:
  stage: docker
  image:
    name: docker:latest
  services:
    - docker:dind   
  script:
    - docker build --build-arg REACT_APP_RAPID_API_KEY=f0ead79813mshb0aa7ddf114a7dap1adb3djsn483b017de1a9 -t youtubev1 .    
    - docker tag youtubev2 maxjith/youtubev2:latest
    - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
    - docker push maxjith/youtubev2:latest

Scan image:
  stage: trivy image scan
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  script:
    - trivy image maxjith/youtubev2:latest

Added stages

Commit changes and it will automatically start building.

Go to Pipelines view

Now click on Docker build and push

Go to Dockerhub and see the image

Now come back to GitLab and click on Trivy image scan

Output raw

Step 5: Install Gitlab Runner on Ec2

Go to GitLab and Click on Settings and CI/CD

Click on Expand at Runners

Click on Three dots and then click on Show Runner installation

Click on Linux and amd64 and copy the commands

Now come back to server Putty or Mobaxtreme

Create a new file

sudo vi gitlab-runner-installation

Paste the below commands into it

Paste the below commands into it

Provide executable permissions and run the script

sudo chmod +x <file-name>
./<file-name>

Installation completed

Start the GitLab runner

sudo gitlab-runner start

Now run the below command or your command to register the runner

Update the token is enough

sudo gitlab-runner register --url https://gitlab.com/ --registration-token <token>

Provide the details for registering the runner

  1. Provide Enter for GitLab.com

  2. For token we already added with token, so click on Enter again

  3. Description as your wish

  4. Tags also and you can use multiple tags by providing a comma after each tga

  5. Maintenance note is just optional

  6. For executors use Shell

Runner added successfully.

Start the GitLab runner

sudo gitlab-runner start

Run the GitLab runner

sudo gitlab-runner run

Go to GitLab and refresh the page once or click on Enable for this project

Click on the Pencil mark to edit

Step 6: Run the Application on the Docker container

Now edit the .gitlab-ci.yml file for the deploy stage

The complete file

Click on save changes.

deploy:
  stage: run container
  tags:
    - youtube        #use your own tags 
  script:
    - docker run -d --name youtube -p 3000:3000 maxjith/youtubev2:latest

Commit changes, it will automatically start to build

If you get an error like this

Comment them

Save and exit from that file and restart GitLab runner

sudo gitlab-runner restart

Now start and Run the GitLab runner


sudo gitlab-runner start
sudo gitlab-runner run

Now go to GitLab → Build → Pipelines

Build completed and click on Deploy job

See the output it ran a container on ec2

Now go to MobaXtreme or Putty and Provide the below command to see running containers.

docker ps

Container running.

Step 7: Access the Application on Browser

Copy the Public IP of the ec2 instance and paste it into the Browser.

Don’t forget to open the 3000 port in the Security Group

<Public-ip:3000>

Output

Step 8: Termination

  1. Delete the personal Access token of the docker.

  2. Delete the containers.

  • docker stop <container name> docker rm <container name>

3. Delete the Ec2 instance.

And there you have it, folks! You’re now the DevOps master of your YouTube app deployment universe. We’ve journeyed through code, quality, security, containers, and automation, all with GitLab as our trusty sidekick. Now it’s your turn to unleash the power of DevOps and take your YouTube app to the next level!