<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sameer's blog]]></title><description><![CDATA[Sameer's blog]]></description><link>https://www.sgawali.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 10:53:29 GMT</lastBuildDate><atom:link href="https://www.sgawali.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Implement End-to-End DevOps on a Go Lang Demo News Application]]></title><description><![CDATA[In the fast-paced world of software development, adopting DevOps practices is essential for efficient workflows, automated pipelines, and quick delivery. If your project isn't "DevOpsified" yet, you might be missing out on the benefits of continuous ...]]></description><link>https://www.sgawali.com/how-to-implement-end-to-end-devops-on-a-go-lang-demo-news-application</link><guid isPermaLink="true">https://www.sgawali.com/how-to-implement-end-to-end-devops-on-a-go-lang-demo-news-application</guid><category><![CDATA[Devops]]></category><category><![CDATA[ArgoCD]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Helm]]></category><dc:creator><![CDATA[Sameer Gawali]]></dc:creator><pubDate>Tue, 22 Oct 2024 13:58:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729587644988/a373570b-301b-42cd-b193-b9f9d5cd01c1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the fast-paced world of software development, adopting DevOps practices is essential for efficient workflows, automated pipelines, and quick delivery. If your project isn't "DevOpsified" yet, you might be missing out on the benefits of continuous integration, containerization, and a smoother deployment process. Today, we're walking through a hands-on approach to transforming a basic Go lang demo news application ("<strong>Demo News App</strong>") into a fully DevOps-enabled project. l will guide you through the complete process, including setting up CI/CD, containerizing the application, creating Kubernetes manifests, and more. Let’s dive right in</p>
<h2 id="heading-step-1-containerization">Step 1 : Containerization</h2>
<p>The first step is to containerize the application using Docker. We will write a multi-stage Dockerfile to ensure that our images are both secure and lightweight. The Dockerfile will include:</p>
<p>A base image for building the application.</p>
<p>A distroless image for running the application.</p>
<p>This approach not only reduces the image size but also enhances security by minimizing the attack surface.</p>
<p>First you need to understand the application. Here we're dealing with a Go-based portfolio web app. So, we will first run the application locally to understand how it works, what ports it uses, and how it’s built.</p>
<p>First, clone the repository from GitHub using:</p>
<pre><code class="lang-plaintext">git clone https://github.com/sgawali/news-demo-app.git
</code></pre>
<p>Now refer to readme file and follow all prerequisites &amp; get started steps to run demo app locally</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729590934383/8f29266f-c650-4f13-87d3-30e714aad52f.png" alt class="image--center mx-auto" /></p>
<p>As shown in screenshot News Demo App will be launched in your browser. We can type any topic to search news related to that topic in search window and then hit enter to view all news related to that topic.</p>
<p>Writing the Multi-Stage DockerFile:</p>
<p>Using a <strong>multi-stage Dockerfile</strong> saves space and adds security layers to the Docker image. We first use Go lang base image to build the app and then copy it into a minimal distribution image, ensuring we reduce the size and potential vulnerabilities.</p>
<p>Here's a snapshot of what the Dockerfile looks like:</p>
<pre><code class="lang-plaintext">FROM golang:1.23 AS base

WORKDIR /app
# We want to populate the module cache based on the go.{mod,sum} files.
COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .

# Build the Go app
RUN go build -o ./out/news-demo-app .

# Start fresh from a smaller distroless image
FROM gcr.io/distroless/base

COPY --from=base /app/out/news-demo-app /app/news-demo-app

COPY --from=base /app/assets ./assets

COPY --from=base /app/news ./news

COPY --from=base /app/index.html .

# This container exposes port 3000 to the outside world
EXPOSE 3000

# Run the binary program produced by `go install`
CMD ["/app/news-demo-app"]
</code></pre>
<p>This Dockerfile is an industry-standard approach. It builds the app, then packages it into a lightweight, <strong>distroless</strong> container which is more secure and faster to deploy.</p>
<p>Once your Dockerfile is ready, you can build and run your image:</p>
<pre><code class="lang-plaintext">docker build -t news-demo-app:v1 .
</code></pre>
<pre><code class="lang-plaintext">docker run -p 3000:3000 go-web-app:v1
</code></pre>
<p>Visit <a target="_blank" href="http://localhost:8080/courses"><code>localhost:3000</code></a> and you'll see your app running in the container!</p>
<h2 id="heading-step-2-creating-kubernetes-manifests">Step 2 : Creating Kubernetes Manifests</h2>
<p>Next we will create kubernetes manifests, including deployment, service and ingress configurations. This will allow us to deploy our application on a kubernetes cluster effectively. The deployment manifests will specify the number of replicas, container image and ports.</p>
<p>Deployment YAML</p>
<pre><code class="lang-yaml">  <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">news-demo-app</span>
  <span class="hljs-attr">labels:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">news-demo-app</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">2</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">news-demo-app</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">news-demo-app</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">news-demo-app</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">samgawali/news-demo-app:v3</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">3000</span>
</code></pre>
<p>Service YAML</p>
<p>A <strong>Service</strong> allows your app to be discoverable</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">news-demo-app</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">news-demo-app</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">ClusterIP</span>
  <span class="hljs-attr">ports:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
    <span class="hljs-attr">targetPort:</span> <span class="hljs-number">3000</span>
    <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>
</code></pre>
<p>Ingress YAML</p>
<p>while an <strong>Ingress</strong> helps map external traffic into your cluster’s services.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.k8s.io/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Ingress</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">news-demo-app</span>
  <span class="hljs-attr">annotations:</span>
    <span class="hljs-attr">nginx.ingress.kubernetes.io/rewrite-target:</span> <span class="hljs-string">/</span>

<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">ingressClassName:</span> <span class="hljs-string">nginx</span>
  <span class="hljs-attr">rules:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">host:</span> <span class="hljs-string">"*.samgawali.com"</span>
    <span class="hljs-attr">http:</span>
      <span class="hljs-attr">paths:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">pathType:</span> <span class="hljs-string">Prefix</span>
        <span class="hljs-attr">path:</span> <span class="hljs-string">"/"</span>
        <span class="hljs-attr">backend:</span>
          <span class="hljs-attr">service:</span>
            <span class="hljs-attr">name:</span> <span class="hljs-string">news-demo-app</span>
            <span class="hljs-attr">port:</span>
              <span class="hljs-attr">number:</span> <span class="hljs-number">80</span>
</code></pre>
<p>At this stage, your app is ready for deployment into a Kubernetes cluster.</p>
<h2 id="heading-step-3-creating-a-kubernetes-cluster">Step 3 : Creating a Kubernetes Cluster</h2>
<p>For production-grade deployments, we'll set up an Civo Kubernetes Cluster</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.civo.com/">https://www.civo.com/</a></div>
<p> </p>
<p>Install the necessary CLI tools including <strong>kubectl</strong>, <strong><em>Civo CLI</em></strong></p>
<p>Authenticate your Civo account using api key</p>
<pre><code class="lang-plaintext">civo apikey add key-name “Your Civo API Key“
</code></pre>
<p>Create the cluster</p>
<pre><code class="lang-plaintext">civo kubernetes create demoapp-cluster --size "g4s.kube.medium" --nodes 2 --wait --save --merge --switch --region FRA1 -r=Traefik -a=Nginx --create-firewall --firewall-rules "80,443:0.0.0.0/0"
</code></pre>
<p>Once done, use <code>kubectl</code> to deploy the Kubernetes manifests you created earlier. A simple <code>kubectl apply</code> command will do the trick:</p>
<pre><code class="lang-plaintext">kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
</code></pre>
<p>Be sure to expose the service using a NodePort or Load Balancer for external access!</p>
<p><strong>Ingress Controller Installation &amp; Configuration</strong></p>
<pre><code class="lang-plaintext">kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
</code></pre>
<p>This will install nginx ingress controller in ingress-nginx namespace</p>
<p>A <strong>Loadbalancer</strong> will be created in Civo Kubernetes Cluster as shown in below screenshot</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729603046183/dcd0e57a-6426-48fd-8bfd-beac5f55c9d8.png" alt class="image--center mx-auto" /></p>
<p><strong>DNS Mapping</strong></p>
<p>We will map our domain to the application using DNS. This will allow users to access the application via a friendly url instead of an ip address. I am using Civo DNS in Civo dashboard to configure my website as DSN for our application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729603474263/cb2ce8f1-b5a7-49fd-aed4-bacdde710b6f.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-step-4-setting-up-helm-chart">Step 4 : Setting Up Helm Chart</h2>
<p>Helm simplifies managing your Kubernetes configs by allowing you to easily deploy to different environments (e.g., Dev, QA, Prod). If you need to deploy the same app across multiple environments with minimal changes, Helm is your go-to tool.</p>
<p>To get started, create a Helm chart:</p>
<pre><code class="lang-plaintext">helm create news-demo-app-chart
</code></pre>
<p>Now delete all sample files in templates folder and copy all our app Kubernetes manifests files into it for details you can refer to my git repository.</p>
<p>Then, define the values for each environment in <strong>values.yaml file</strong></p>
<p>Test if generated helm chart is perfect or not with below commands</p>
<pre><code class="lang-plaintext">helm lint ./news-demo-app-chart    

helm template ./news-demo-app-chart 

helm install news-demo-app ./news-demo-app-chart --dry-run
</code></pre>
<p>Deploy the Helm chart with a command :</p>
<pre><code class="lang-plaintext">helm install go-web-app ./go-web-app-chart
</code></pre>
<h2 id="heading-step-5-implementing-continuous-integration-ci-with-github-actions">Step 5 : Implementing Continuous Integration (CI) with GitHub Actions</h2>
<p>GitHub Actions is a powerful tool to automate your development workflows. Here's how you set up CI for the app:</p>
<h3 id="heading-create-a-github-actions-workflow">Create a GitHub Actions Workflow</h3>
<p>Under <code>.github/workflows/ci.yml</code>, implement several stages:</p>
<ul>
<li><p><strong>Build and Test</strong>: Automatically build the Go app whenever code is pushed.</p>
</li>
<li><p><strong>Test</strong>: Test Go app</p>
</li>
<li><p><strong>Docker Image Build &amp; Push</strong>: After tests pass, push the Docker image to Docker Hub.</p>
</li>
<li><p><strong>Update Helm</strong>: Push the updated Helm values file with the latest Docker image.</p>
</li>
</ul>
<p>Here’s a snippet from the workflow:</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># CICD using GitHub actions</span>

<span class="hljs-attr">name:</span> <span class="hljs-string">CI/CD</span>

<span class="hljs-comment"># Exclude the workflow to run on changes to the helm chart</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>
    <span class="hljs-attr">paths-ignore:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'helm/**'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'k8s/**'</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">'README.md'</span>

<span class="hljs-attr">jobs:</span>

  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Go</span> <span class="hljs-number">1.23</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-go@v2</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">go-version:</span> <span class="hljs-number">1.23</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">go</span> <span class="hljs-string">build</span> 



  <span class="hljs-attr">code-quality:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Test</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">go</span> <span class="hljs-string">test</span>



  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">needs:</span> <span class="hljs-string">build</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Docker</span> <span class="hljs-string">Buildx</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">docker/setup-buildx-action@v1</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Login</span> <span class="hljs-string">to</span> <span class="hljs-string">DockerHub</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">docker/login-action@v3</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">username:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.DOCKERHUB_USERNAME</span> <span class="hljs-string">}}</span>
        <span class="hljs-attr">password:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.DOCKERHUB_TOKEN</span> <span class="hljs-string">}}</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">and</span> <span class="hljs-string">Push</span> <span class="hljs-string">action</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">docker/build-push-action@v6</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">context:</span> <span class="hljs-string">.</span>
        <span class="hljs-attr">file:</span> <span class="hljs-string">./Dockerfile</span>
        <span class="hljs-attr">push:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">tags:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.DOCKERHUB_USERNAME</span> <span class="hljs-string">}}/news-demo-app:${{github.run_id}}</span>

  <span class="hljs-attr">update-newtag-in-helm-chart:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">needs:</span> <span class="hljs-string">push</span>

    <span class="hljs-attr">steps:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">repository</span>
      <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v4</span>
      <span class="hljs-attr">with:</span>
        <span class="hljs-attr">token:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.TOKEN</span> <span class="hljs-string">}}</span>

    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Update</span> <span class="hljs-string">tag</span> <span class="hljs-string">in</span> <span class="hljs-string">Helm</span> <span class="hljs-string">chart</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">|
        sed -i 's/tag: .*/tag: "${{github.run_id}}"/' helm/news-demo-app-chart/values.yaml
</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Commit</span> <span class="hljs-string">and</span> <span class="hljs-string">push</span> <span class="hljs-string">changes</span>
      <span class="hljs-attr">run:</span> <span class="hljs-string">|
        git config --global user.email "sameer@sgawali.com"
        git config --global user.name "sgawali"
        git add helm/news-demo-app-chart/values.yaml
        git commit -m "Update tag in Helm chart"
        git push</span>
</code></pre>
<p>Now, pushing to the repo triggers automated testing, Docker pushing, and Helm updates.</p>
<h2 id="heading-step-6-continuous-delivery-cd-with-argo-cd">Step : 6 Continuous Delivery (CD) with Argo CD</h2>
<p>Argo CD provides a seamless way to implement <strong>GitOps</strong>, allowing automatic updates to your Kubernetes cluster every time there’s a new version.</p>
<h3 id="heading-install-argo-cd">Install Argo CD</h3>
<p>Run the following to install Argo CD in your Kubernetes cluster:</p>
<pre><code class="lang-yaml"><span class="hljs-string">kubectl</span> <span class="hljs-string">apply</span> <span class="hljs-string">-n</span> <span class="hljs-string">argocd</span> <span class="hljs-string">-f</span> <span class="hljs-string">https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml</span>
</code></pre>
<h3 id="heading-set-up-argo-cd">Set Up Argo CD</h3>
<p>Install a Helm chart directly through Argo CD by creating a new app in the Argo CD dashboard:</p>
<ol>
<li><p>Set the project to "default."</p>
</li>
<li><p>Connect to the GitHub repository.</p>
</li>
<li><p>Specify the path to your Helm chart and set the sync policy to <strong>Automatic.</strong></p>
</li>
</ol>
<p>Now, Argo CD will monitor the Helm chart for new changes and deploy updated versions without any manual intervention!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729604648971/82dfa61d-db06-4bf1-8935-f8bd26cacc8a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729604746618/bd7aa543-460d-49da-83b6-f2b8a8fb86ae.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729604765678/54100718-6fde-41ca-932e-ee0f4db1f40e.png" alt class="image--center mx-auto" /></p>
<p>As shown in Screenshots our News demo application is now accessible on my websites for which i have created DNS records. A change in app’s source code will automatically trigger Ci/CD pipelines and changes will be deployed automatically by Argo CD tool.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>When you take a non-DevOps project and transform it into a fully automated, scalable, and reliable system, the possibilities are endless. We started with a basic Go lang demo news app and implemented a full DevOps cycle: containerizing the app, deploying it in Kubernetes with Helm, and automating continuous integration and deployment using GitHub Actions and Argo CD.</p>
<p>Now, it’s time for you to give it a shot! Check out the project repositories, follow the steps, and "DevOpsify" your next project.</p>
]]></content:encoded></item><item><title><![CDATA[GitLab CI/CD YouTube App Deployment]]></title><description><![CDATA[In today’s software development landscape, speed and reliability are paramount. Continuous Integration and Continuous Deployment (CI/CD) pipelines offer a way to automate and streamline your development and deployment processes. In this guide, we’ll ...]]></description><link>https://www.sgawali.com/gitlab-cicd-youtube-app-deployment</link><guid isPermaLink="true">https://www.sgawali.com/gitlab-cicd-youtube-app-deployment</guid><dc:creator><![CDATA[Sameer Gawali]]></dc:creator><pubDate>Mon, 24 Jun 2024 20:28:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1719231218999/e4c7eee4-82b8-4c48-905f-bce5b1016eee.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In today’s software development landscape, speed and reliability are paramount. Continuous Integration and Continuous Deployment (CI/CD) pipelines offer a way to automate and streamline your development and deployment processes. In this guide, we’ll show you how to set up a complete CI/CD pipeline for a React YouTube app clone using GitLab.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719231489521/73be2531-4039-4cb6-9b90-75ea9dfee3ff.png" alt class="image--center mx-auto" /></p>
<p>Picture this: we are creating a YouTube-like platform where users can explore videos and channels. It’s a fantastic project, but managing the development workflow can be complex. That’s where GitLab CI/CD comes in, offering a straightforward and powerful solution to automate your work.</p>
<p>This step-by-step tutorial is for developers and devops enthusiasts looking to make their projects more efficient with CI/CD. By the end, you’ll know how to set up a robust CI/CD pipeline, including automated testing, code quality checks, and secure containerization. Let’s embark on this journey together and see how CI/CD can transform your development experience while building a React YouTube app clone.</p>
<p>Ready? Let’s simplify CI/CD and make your development life easier!</p>
<p>Step 1: Create an API key for Youtube.</p>
<p>Step 2: Create a Repository and push it to GitLab.</p>
<p>Step 3: Launch an Ec2 instance and run Sonarqube on it.</p>
<p>Step 4A: Create a <code>.gitlab-ci.yml</code> File.</p>
<p>Step 4B: Add the required variables for the project.</p>
<p>Step 5: Install Gitlab Runner on Ec2.</p>
<p>Step 6: Run the Application on the Docker container.</p>
<p>Step 7: Access the Application on Browser.</p>
<h3 id="heading-step-1-create-an-api-key-from-rapid-api">Step 1: Create an API key from Rapid API</h3>
<p>Open a new tab in the browser and search for <a target="_blank" href="http://rapidapi.com/"><strong>rapidapi.com</strong></a></p>
<p>It will automatically provide your mail and select a mail to create an account</p>
<p>You will see the page like this and click on signup</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719231878729/35b4c962-2bd2-4114-8be5-ced4817a5942.avif" alt class="image--center mx-auto" /></p>
<p>Now click on Sign Up with Google</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719232032371/0be4adf0-c127-40aa-83cb-bbb8bd6f1fc0.avif" alt class="image--center mx-auto" /></p>
<p>Select your mail here</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719232428620/d77a4eb5-210c-4ce9-b629-a5f9c9b71ddc.png" alt class="image--center mx-auto" /></p>
<p>It will automatically create your account now</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719232837737/de3b346a-4509-45fe-b427-bad9ef70157c.png" alt class="image--center mx-auto" /></p>
<p>Now in the search bar search for YouTube and select YouTube v3</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719232919513/e808fd7a-c24a-4a4c-b2aa-b5253b5c3075.avif" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719233656659/e49a6f70-b693-41f4-bd90-4a80da54a678.png" alt class="image--center mx-auto" /></p>
<p>Copy API Key as shown in screenshot and save it for further use at the docker stage.</p>
<p>docker build –build-arg REACT_APP_RAPID_API_KEY=<mark>&lt;API-KEY&gt;</mark> -t ${imageName} .</p>
<h3 id="heading-step-2-create-a-repository-and-push-it-to-gitlab">Step 2: Create a Repository and push it to GitLab</h3>
<p>Go to <a target="_blank" href="http://gitlab.com/">GitLab.com</a> and login to your account</p>
<p>Click on New Project</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719234100945/74e47604-2b44-4d63-8e79-62772ca0a13b.avif" alt class="image--center mx-auto" /></p>
<p>Click on Create Blank Project</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719234152767/d36594e2-71cf-4f2d-9def-7d2aedeb35e1.avif" alt class="image--center mx-auto" /></p>
<p>Provide a name for the Project</p>
<p>Keep Visibility to the public</p>
<p>Uncheck the Readme and create the Project</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719234223172/30cfaf8a-10b9-44dc-84d6-e03e58b65580.avif" alt class="image--center mx-auto" /></p>
<p>Use the below commands to push code to GitLab</p>
<pre><code class="lang-plaintext">cd existing_folder
git init --initial-branch=main
git remote add origin https://gitlab.com/sgawali/youtubev1.git
git add .
git commit -m "Initial commit"
git push --set-upstream origin main
</code></pre>
<p>Files pushed to GitLab</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719236845153/561c7fa4-850c-4383-8d0a-13e1b4562244.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-step-3-launch-an-ec2-instance-and-run-sonarqube-on-it">Step 3: Launch an Ec2 instance and run Sonarqube on it</h3>
<p><strong>Log into AWS Console:</strong> Sign in to your AWS account.</p>
<p><strong>Launch an Instance:</strong></p>
<p>Choose <strong>“EC2”</strong> from services. Click “Launch Instance.”</p>
<p><strong>Choose an AMI:</strong> Select an Ubuntu image.</p>
<p><strong>Choose an Instance Type:</strong> Pick “t2.medium.”</p>
<p><strong>Key Pair:</strong> Choose an existing key pair or create a new one.</p>
<p><strong>Configure Security Group:</strong></p>
<p>Create a new security group. Add rules for HTTP, and HTTPS, and open all ports for learning purposes. Add Storage: Allocate at least 10 GB of storage.</p>
<p><strong>Launch Instance:</strong> Review and launch the instance.</p>
<p>Access Your Instance: Use SSH to connect to your instance with the private key.</p>
<p>Keep in mind, that opening all ports is not recommended for production environments; it’s just for educational purposes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719238375690/360def43-ade4-4dac-bf7a-aaf7fba37206.avif" alt class="image--center mx-auto" /></p>
<p><strong>Connect to Your EC2 Instance and install docker:</strong></p>
<p>Run the below commands to install the docker</p>
<pre><code class="lang-bash">sudo apt-get update
sudo apt-get install docker.io -y
sudo usermod -aG docker <span class="hljs-variable">$USER</span>   <span class="hljs-comment">#my case is ubuntu</span>
newgrp docker
sudo chmod 777 /var/run/docker.sock
</code></pre>
<p>After the docker installation, we will create a Sonarqube container (Remember to add 9000 ports in the security group).</p>
<p>Run this command on your EC2 instance to create a SonarQube container:</p>
<pre><code class="lang-bash">docker run -d --name sonar -p 9000:9000 sonarqube:lts-community
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719238825684/f982604f-59c8-4f2b-bff0-245c1f717e1a.avif" alt class="image--center mx-auto" /></p>
<p>Now copy the IP address of the ec2 instance</p>
<pre><code class="lang-plaintext">&lt;ec2-public-ip:9000&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719238995076/b67b7180-ef3c-481a-9150-ed1092482845.avif" alt class="image--center mx-auto" /></p>
<p>Enter username and password, click on login and change password</p>
<pre><code class="lang-plaintext">username admin
password admin
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719239085490/352d5259-8135-4509-a908-cfb8df52027d.avif" alt class="image--center mx-auto" /></p>
<p>Update New password, This is Sonar Dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1694159887297/6e055b5c-13ea-405f-bc13-1234b05bf2ff.png?auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp&amp;auto=compress,format&amp;format=webp" alt /></p>
<h3 id="heading-step-4a-create-a-gitlab-ciyml-file">Step 4A: Create a <code>.gitlab-ci.yml</code> File.</h3>
<p>Now go to GitLab click on ‘+’ and click on Newfile</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719239341779/4243b79c-7fb3-4af2-a424-7100964bf195.png" alt class="image--center mx-auto" /></p>
<p>File name <code>.gitlab-ci.yml</code></p>
<p>Content</p>
<pre><code class="lang-yaml"><span class="hljs-attr">stages:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span>

<span class="hljs-attr">Install dependecy:</span>
    <span class="hljs-attr">stage:</span> <span class="hljs-string">npm</span>    
    <span class="hljs-attr">image:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">node:16</span>
    <span class="hljs-attr">script:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699452609575/a9a0d794-a5c7-4501-8d9d-93f093441e8d.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Commit the changes and it will automatically start the build</p>
<p>Now click on Build and Pipelines</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719240918577/de678a26-ed71-4f31-b4cc-3873164e9f75.png" alt class="image--center mx-auto" /></p>
<p>Now click on Running.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719242090972/bc88238d-bc9c-479e-970f-cf0968622149.png" alt class="image--center mx-auto" /></p>
<p>Click on Install dependency</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719243135897/747451d1-723e-472e-9336-16cde2c8c556.png" alt class="image--center mx-auto" /></p>
<p>You will see build output</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719243637198/ed29467c-8e03-43a4-8e3d-22d6f0442e93.png" alt class="image--center mx-auto" /></p>
<p>Now add the Sonarqube stage to the pipeline</p>
<p>Go to the Sonarqube dashboard and click on Manually.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453113737/703cb437-6072-4c62-b4f5-b3182244e91c.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Provide the name of the Project and click on Setup</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453190201/9e10f50d-a125-41a8-b400-4b24b4df6944.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Select the CI tool as GitLab CI</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453238357/cf6ae97a-a6fd-4d28-8a7e-0505cf3dc032.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Select Other because we are using the JS App</p>
<p>It will provide code and we need to create a file inside our repo</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453308067/e9219457-2bba-4ca3-84c9-3933ec1092cf.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Go to Gitlab and click on + and Newfile</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719244406839/b1a3f886-15a5-45bf-87a2-56b6a14a2816.png" alt class="image--center mx-auto" /></p>
<p>Filename is <a target="_blank" href="http://sonar-project.properties"><code>sonar-project.properties</code></a></p>
<p>Paste the content that you got from Sonarqube</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453515944/6a8cd5e1-80b4-4b72-9958-8c704182f741.png?auto=compress,format&amp;format=webp" alt /></p>
<p>The file looks like this and click on commit changes</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453557845/3badc428-61bc-40b8-b30b-d69b3b52f4c7.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Go to Sonarqube and click on continue</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699453614668/8ef310fb-7306-4863-9f0b-2eebf6d80ad0.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now it will provide Variables to add to our GitLab</p>
<h3 id="heading-step-4b-add-the-required-variables-for-the-project">Step 4B: Add the required variables for the project.</h3>
<p>Variables Generated</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699454672224/22cea9c4-f102-44af-babb-4a4e1a5c77e7.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go to GitLab</p>
<p>Click on settings and CI/CD</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719244936845/21fd7a2f-36e7-44fb-b484-295a541e5692.png" alt class="image--center mx-auto" /></p>
<p>Click on Expand in variables</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719245189011/875099fb-4224-452e-94a7-d1b41d47e819.png" alt class="image--center mx-auto" /></p>
<p>Click on Add variable</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719245412756/82270e4e-7d68-4e3a-a8fd-219565198dd2.png" alt class="image--center mx-auto" /></p>
<p>Now go back to Sonarqube and copy the Key</p>
<p>Click on Generate a token</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699455069519/8d9b9784-ee94-45f4-b31d-2fc489cb8fe1.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Again Click on Generate</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699455192574/d7b64024-d697-4994-bfcf-a1e992242864.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Copy the token</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699455122645/0fee8721-f955-4823-ad72-96fb76c81d06.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now come back to GitLab and add them like the below image and click on add variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699455326754/a3e4c640-3d74-45c5-a384-c693b12762ae.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Sonar token is added</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458436039/80e686d4-fb61-4290-ac95-c9cf10fe0bab.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go to the Sonarqube Dashboard again</p>
<p>Let’s add another variable, copy them</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458516421/555516f9-2dfa-432c-884f-a74940e1bbab.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go to GitLab and click on Add variable</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458605982/ffec759c-7dae-40f5-a298-dd9d6ce8bbea.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Add the copied values like the below image</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458655369/84b8e4c3-4521-4ff2-aa33-ec1dff726c0f.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Two variables were added.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458724321/4d614a87-4c37-482b-98f0-de7f46311159.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go back to the Sonarqube Dashboard</p>
<p>Click on continue</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458788856/9016e8c4-c62f-46fd-a3ba-c632ae12a52d.png?auto=compress,format&amp;format=webp" alt /></p>
<p>It will provide and CI configuration file copy it and use it inside our <code>.gitlab-ci.yml</code> file</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699458903130/777eab4b-46a2-4cd9-897a-89d6ec124d08.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go back to GitLab and edit the <code>.gitlab-ci.yml</code> file</p>
<p>Full file (update with your content)</p>
<pre><code class="lang-yaml"><span class="hljs-attr">stages:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar</span>
<span class="hljs-attr">Install dependecy:</span>
    <span class="hljs-attr">stage:</span> <span class="hljs-string">npm</span>
    <span class="hljs-attr">image:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">node:16</span>
    <span class="hljs-attr">script:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-attr">sonarqube-check:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">sonar</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">sonarsource/sonar-scanner-cli:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">variables:</span>
    <span class="hljs-attr">SONAR_USER_HOME:</span> <span class="hljs-string">"${CI_PROJECT_DIR}/.sonar"</span>  <span class="hljs-comment"># Defines the location of the analysis task cache</span>
    <span class="hljs-attr">GIT_DEPTH:</span> <span class="hljs-string">"0"</span>  <span class="hljs-comment"># Tells git to fetch all the branches of the project, required by the analysis task</span>
  <span class="hljs-attr">cache:</span>
    <span class="hljs-attr">key:</span> <span class="hljs-string">"${CI_JOB_NAME}"</span>
    <span class="hljs-attr">paths:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.sonar/cache</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-scanner</span>
  <span class="hljs-attr">allow_failure:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">only:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699459068250/84f95e79-99a8-4555-9f45-4a7c2984f82e.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Commit changes and it will automatically start the build.</p>
<p>Click on Build –&gt; Pipelines</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719249426976/5f0e9d07-9157-4e55-8e0d-08cfe8c1730b.png" alt class="image--center mx-auto" /></p>
<p>Click on Running</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719249791618/ff0a008a-ccbb-4140-9863-6933174a5949.png" alt class="image--center mx-auto" /></p>
<p>Now click on Sonarqube-check</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719250127604/8854505d-fa9f-4286-86ea-62ec9c0deddb.png" alt class="image--center mx-auto" /></p>
<p>Build output</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699459421037/66465bd9-851a-4624-bd5d-d27a60d64c42.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now add the next stage of the Trivy file scan</p>
<p>Update the <code>.gitlab-ci.yml</code> file</p>
<pre><code class="lang-yaml"><span class="hljs-attr">stages:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
<span class="hljs-attr">Install dependecy:</span>
    <span class="hljs-attr">stage:</span> <span class="hljs-string">npm</span>
    <span class="hljs-attr">image:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">node:16</span>
    <span class="hljs-attr">script:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-attr">sonarqube-check:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">sonar</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">sonarsource/sonar-scanner-cli:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">variables:</span>
    <span class="hljs-attr">SONAR_USER_HOME:</span> <span class="hljs-string">"${CI_PROJECT_DIR}/.sonar"</span>  <span class="hljs-comment"># Defines the location of the analysis task cache</span>
    <span class="hljs-attr">GIT_DEPTH:</span> <span class="hljs-string">"0"</span>  <span class="hljs-comment"># Tells git to fetch all the branches of the project, required by the analysis task</span>
  <span class="hljs-attr">cache:</span>
    <span class="hljs-attr">key:</span> <span class="hljs-string">"${CI_JOB_NAME}"</span>
    <span class="hljs-attr">paths:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.sonar/cache</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-scanner</span>
  <span class="hljs-attr">allow_failure:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">only:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>
<span class="hljs-attr">Trivy file scan:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">aquasec/trivy:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">fs</span> <span class="hljs-string">.</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699459867536/6b14f916-3182-44ba-a2d6-efa6c2fbcbac.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Commit changes and go to pipeline stages</p>
<p>Click on the Trivy file scan</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719250452779/8b09ffd1-7401-4a9a-a2dd-09289c61b800.png" alt class="image--center mx-auto" /></p>
<p>Build output</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699460035893/569b64ca-54f5-4d18-8c57-0e0e41a6a168.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Add the Docker build and push stage</p>
<p>Before that Add docker credentials to GitLab Variables as secrets.</p>
<p>Go to the docker hub and create a Personal Access token</p>
<p>Click on your profile name and Account Settings</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719250950781/80889dc4-8036-40c1-a934-5e7fb47a9212.png" alt class="image--center mx-auto" /></p>
<p>Now click on Security –&gt; New Access Token</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719251089992/f029ec93-7268-43a9-92c6-b22dcdc5a0bd.png" alt class="image--center mx-auto" /></p>
<p>Provide a name –&gt; Generate</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719251394759/4931e29e-9d4e-463e-857f-47a7ee6ef7eb.png" alt class="image--center mx-auto" /></p>
<p>Now copy the token and keep it safe</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719251742649/1e5fd223-3e61-40dd-93b4-5e3daeabd075.png" alt class="image--center mx-auto" /></p>
<p>Now go back to Gitlab</p>
<p>Click on settings and CI/CD</p>
<p>Click on Expand in variables</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719252066740/e3795b3a-e765-45ec-a0d1-41b01b13e3b6.png" alt class="image--center mx-auto" /></p>
<p>Click on Add variable</p>
<p>Use your DockerHub username in value and Add variable</p>
<p>Key DOCKER_USERNAME</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719254220644/5dfa0c8c-de36-4d51-bd01-6bb94be9b53c.png" alt class="image--center mx-auto" /></p>
<p>Click on Add variable again</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699461254121/79877f0e-4100-4ad6-a527-901f1ac169dd.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Key DOCKER_PASSWORD</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719254181515/79307659-0c0d-417d-8985-b2fbed60fe40.png" alt class="image--center mx-auto" /></p>
<p>Variables added</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699461412146/24f15467-af4d-4b2a-a8ec-00773b031e48.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now add the below stage to the Configuration <code>.gitlab-ci.yml</code> file</p>
<p>Added Docker and Trivy image scan stages</p>
<pre><code class="lang-yaml"><span class="hljs-attr">stages:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">scan</span>
<span class="hljs-attr">Install dependecy:</span>
    <span class="hljs-attr">stage:</span> <span class="hljs-string">npm</span>
    <span class="hljs-attr">image:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">node:16</span>
    <span class="hljs-attr">script:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-attr">sonarqube-check:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">sonar</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">sonarsource/sonar-scanner-cli:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">variables:</span>
    <span class="hljs-attr">SONAR_USER_HOME:</span> <span class="hljs-string">"${CI_PROJECT_DIR}/.sonar"</span>  <span class="hljs-comment"># Defines the location of the analysis task cache</span>
    <span class="hljs-attr">GIT_DEPTH:</span> <span class="hljs-string">"0"</span>  <span class="hljs-comment"># Tells git to fetch all the branches of the project, required by the analysis task</span>
  <span class="hljs-attr">cache:</span>
    <span class="hljs-attr">key:</span> <span class="hljs-string">"${CI_JOB_NAME}"</span>
    <span class="hljs-attr">paths:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.sonar/cache</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-scanner</span>
  <span class="hljs-attr">allow_failure:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">only:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>
<span class="hljs-attr">Trivy file scan:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">aquasec/trivy:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">fs</span> <span class="hljs-string">.</span>
<span class="hljs-attr">Docker build and push:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">docker</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">docker:latest</span>
  <span class="hljs-attr">services:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker:dind</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">build</span> <span class="hljs-string">--build-arg</span> <span class="hljs-string">REACT_APP_RAPID_API_KEY=f0ead79813mshb0aa7ddf114a7dap1adb3djsn483b017de1a9</span> <span class="hljs-string">-t</span> <span class="hljs-string">youtubev1</span> <span class="hljs-string">.</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">tag</span> <span class="hljs-string">youtubev1</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">login</span> <span class="hljs-string">-u</span> <span class="hljs-string">$DOCKER_USERNAME</span> <span class="hljs-string">-p</span> <span class="hljs-string">$DOCKER_PASSWORD</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">push</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
<span class="hljs-attr">Scan image:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">scan</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">aquasec/trivy:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
</code></pre>
<p>Added stages</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699461630726/95375272-9cff-40ac-9314-ed7170081d1a.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Commit changes and it will automatically start building.</p>
<p>Go to Pipelines view</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699461750535/b0365c17-c9a0-4210-bd8b-5cccaee8350d.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now click on Docker build and push</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719255143750/59deb712-3b6d-4202-b365-3eccdb668f1e.png" alt class="image--center mx-auto" /></p>
<p>Build view</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699462057276/407cc0f4-cd34-4536-9493-1608ec076939.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Go to Dockerhub and see that docker image is uploaded there</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719255855391/c5dbffae-5a82-479b-b57f-70a8c83b7487.png" alt class="image--center mx-auto" /></p>
<p>Now come back to GitLab and click on Trivy image scan</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719256567053/fb9b1a0e-af36-48e5-b29a-d4b86c12cd28.png" alt class="image--center mx-auto" /></p>
<p>Output Log</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699462215958/0dc44340-f401-4db8-b895-c29239cd7ed2.png?auto=compress,format&amp;format=webp" alt /></p>
<h3 id="heading-step-5-install-gitlab-runner-on-ec2">Step 5: Install Gitlab Runner on Ec2</h3>
<p>Go to GitLab and Click on Settings and CI/CD</p>
<p>Click on Expand at Runners</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719256765960/8f750968-1244-4c3f-8da0-9917b9e86eda.png" alt class="image--center mx-auto" /></p>
<p>Click on Three dots and then click on Show Runner installation</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699496481444/b65ca11e-c3ed-482b-b88f-ca09de982e91.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Click on Linux and amd64 and copy the commands</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699496578546/89e00113-ad74-49e5-8429-8afbe613432e.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now come back to Putty or Mobaxtreme</p>
<p>Create a new file</p>
<pre><code class="lang-plaintext">sudo vi gitlab-runner-installation
</code></pre>
<p>Paste the below commands into it</p>
<pre><code class="lang-plaintext"># Download the binary for your system
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
# Give it permission to execute
sudo chmod +x /usr/local/bin/gitlab-runner
# Create a GitLab Runner user
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
# Install and run as a service
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699496847567/f7d6b7b4-8911-4716-a005-3fc9a40aea8e.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Provide executable permissions and run the script</p>
<pre><code class="lang-plaintext">sudo chmod +x &lt;file-name&gt;
./&lt;file-name&gt;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699496912602/8b0ce19c-9936-4af7-a31a-ef9bdff61ca6.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Installation completed</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699496951977/da63c9a2-7b9b-4704-8773-f48e6df332db.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Start the GitLab runner</p>
<pre><code class="lang-plaintext">sudo gitlab-runner start
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497141540/d2f13a08-dbe8-4a69-b6cc-53d959a576b0.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now run the below command or your command to register the runner</p>
<p>Update the token is enough</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497176944/40784d71-02ec-4ea2-9a2a-a27bc2ef176e.png?auto=compress,format&amp;format=webp" alt /></p>
<pre><code class="lang-plaintext">sudo gitlab-runner register --url https://gitlab.com/ --registration-token &lt;token&gt;
</code></pre>
<p>Provide the details for registering the runner</p>
<ol>
<li><p>Provide Enter for <a target="_blank" href="http://gitlab.com/">GitLab.com</a></p>
</li>
<li><p>For token we already added with token, so click on Enter again</p>
</li>
<li><p>Description as your wish</p>
</li>
<li><p>Tags also and you can use multiple tags by providing a comma after each tga</p>
</li>
<li><p>Maintenance note is just optional</p>
</li>
<li><p>For executors use Shell</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497412725/c1a2fa03-a00f-4680-a063-9a7628a70c25.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Runner added successfully.</p>
<p>Start the GitLab runner</p>
<pre><code class="lang-plaintext">sudo gitlab-runner start
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497141540/d2f13a08-dbe8-4a69-b6cc-53d959a576b0.png" alt /></p>
<p>Run the GitLab runner</p>
<pre><code class="lang-plaintext">sudo gitlab-runner run
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497647142/86e76d77-d0c1-4f8f-b33c-235fccd872bf.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Go to GitLab and refresh the page once or click on Enable for this project</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497778257/f644495c-f055-4248-9284-44170acd350d.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now the runner is active and waiting for jobs</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497860970/90704675-cf26-476e-988f-aa19d1a4839e.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Click on the Pencil mark to edit</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699497961772/47ae60e1-4bd3-44cb-9ed2-1ea5a54e206f.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Click on the Check box to indicate whether this runner can pick jobs without tags.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699498014680/42aeb192-53e8-4034-af22-dcd8f824a6e1.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Click on save changes.</p>
<h3 id="heading-step-6-run-the-application-on-the-docker-container">Step 6: Run the Application on the Docker container</h3>
<p>Now edit the <code>.gitlab-ci.yml</code> file for the deploy stage</p>
<p>The complete file</p>
<pre><code class="lang-yaml"><span class="hljs-attr">stages:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">scan</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">run</span> <span class="hljs-string">container</span>
<span class="hljs-attr">Install dependecy:</span>
    <span class="hljs-attr">stage:</span> <span class="hljs-string">npm</span>
    <span class="hljs-attr">image:</span>
        <span class="hljs-attr">name:</span> <span class="hljs-string">node:16</span>
    <span class="hljs-attr">script:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-attr">sonarqube-check:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">sonar</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">sonarsource/sonar-scanner-cli:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">variables:</span>
    <span class="hljs-attr">SONAR_USER_HOME:</span> <span class="hljs-string">"${CI_PROJECT_DIR}/.sonar"</span>  <span class="hljs-comment"># Defines the location of the analysis task cache</span>
    <span class="hljs-attr">GIT_DEPTH:</span> <span class="hljs-string">"0"</span>  <span class="hljs-comment"># Tells git to fetch all the branches of the project, required by the analysis task</span>
  <span class="hljs-attr">cache:</span>
    <span class="hljs-attr">key:</span> <span class="hljs-string">"${CI_JOB_NAME}"</span>
    <span class="hljs-attr">paths:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.sonar/cache</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">sonar-scanner</span>
  <span class="hljs-attr">allow_failure:</span> <span class="hljs-literal">true</span>
  <span class="hljs-attr">only:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">main</span>
<span class="hljs-attr">Trivy file scan:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">trivy</span> <span class="hljs-string">file</span> <span class="hljs-string">scan</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">aquasec/trivy:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">fs</span> <span class="hljs-string">.</span>
<span class="hljs-attr">Docker build and push:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">docker</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">docker:latest</span>
  <span class="hljs-attr">services:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker:dind</span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">build</span> <span class="hljs-string">--build-arg</span> <span class="hljs-string">REACT_APP_RAPID_API_KEY=f0ead79813mshb0aa7ddf114a7dap1adb3djsn483b017de1a9</span> <span class="hljs-string">-t</span> <span class="hljs-string">youtubev1</span> <span class="hljs-string">.</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">tag</span> <span class="hljs-string">youtubev1</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">login</span> <span class="hljs-string">-u</span> <span class="hljs-string">$DOCKER_USERNAME</span> <span class="hljs-string">-p</span> <span class="hljs-string">$DOCKER_PASSWORD</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">push</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
<span class="hljs-attr">Scan image:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">scan</span>
  <span class="hljs-attr">image:</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">aquasec/trivy:latest</span>
    <span class="hljs-attr">entrypoint:</span> [<span class="hljs-string">""</span>]
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">trivy</span> <span class="hljs-string">image</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
<span class="hljs-attr">deploy:</span>
  <span class="hljs-attr">stage:</span> <span class="hljs-string">run</span> <span class="hljs-string">container</span>
  <span class="hljs-attr">tags:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">youtube</span>        <span class="hljs-comment">#use your own tags </span>
  <span class="hljs-attr">script:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">docker</span> <span class="hljs-string">run</span> <span class="hljs-string">-d</span> <span class="hljs-string">--name</span> <span class="hljs-string">youtube</span> <span class="hljs-string">-p</span> <span class="hljs-number">3000</span><span class="hljs-string">:3000</span> <span class="hljs-string">sevenajay/youtubev1:latest</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699498330575/911dcf06-c765-472d-9365-9deb15d40aa7.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Commit changes, it will automatically start to build</p>
<p>Click on Build –&gt; Pipelines</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699498482326/67580d52-ac14-4366-8311-486ca6992da3.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Click on Running</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719258453250/269dc249-b703-4367-bec1-3111fb7a1cd5.png" alt class="image--center mx-auto" /></p>
<p>The last stage is added to the Pipeline</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699498599684/c6df4448-104e-4f6c-ad2c-47c89b0b2e3f.png?auto=compress,format&amp;format=webp" alt /></p>
<p>If you get an error like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699502625809/10f5e76f-0f2a-4c1b-9476-c127137424cd.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Go to GitLab and click on deploy job</p>
<p>Let’s see what is the error</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719258794797/0e17d435-122d-461e-bf77-abfe7732f78e.png" alt class="image--center mx-auto" /></p>
<p>If you get an error like this, click on that link</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719259095133/af9728af-6cc9-4052-b395-9a3f37aaf9a5.png" alt class="image--center mx-auto" /></p>
<p>It will open a new tab and provide a solution for that</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699502840964/4e11fc1d-5470-4f3d-9409-b8aa87bb6bea.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go to Mobaxtreme and stop the Runner</p>
<p>Go to root and use the below commands</p>
<pre><code class="lang-plaintext">sudo su
sudo vi /home/gitlab-runner/.bash_logout
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699502967163/b6b738e4-55ef-47c2-9b11-b4161be5a892.png?auto=compress,format&amp;format=webp" alt /></p>
<p>You will see file like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699503008404/5065157e-8f53-4b3e-8498-0be4ebeb725a.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Comment all lines</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699503040759/93a93949-7031-4514-9917-fa1af41d0841.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Save and exit from that file and restart GitLab runner</p>
<pre><code class="lang-plaintext">sudo gitlab-runner restart
exit #from root
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699506206570/47caec6b-d6e8-4be7-9e1f-6bed8c93b7b7.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now start and Run the GitLab runner</p>
<pre><code class="lang-plaintext">sudo gitlab-runner start
sudo gitlab-runner run
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699506253690/007c6be8-483c-4d76-a15d-6119fcb539e7.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Now go to GitLab –&gt; Build –&gt; Pipelines</p>
<p>Click on Run Pipeline</p>
<p>Build completed and click on Deploy job</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719259617203/3f1cbb04-d5e0-4e4e-99ac-c7be27881c9f.png" alt class="image--center mx-auto" /></p>
<p>See the output it ran a container on ec2 instance</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719259890899/24352770-e7b4-495a-8a3b-7f2d52d8311c.png" alt class="image--center mx-auto" /></p>
<p>Now go to MobaXtreme or Putty connect to ec2 instance and Provide the below command to see running containers.</p>
<pre><code class="lang-plaintext">docker ps
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699506425447/c92295b1-6c54-4f31-b826-48dd34ccda51.png?auto=compress,format&amp;format=webp" alt /></p>
<p>Container running.</p>
<h3 id="heading-step-7-access-the-application-on-browser">Step 7: Access the Application on Browser</h3>
<p>Copy the Public IP of the ec2 instance and paste it into the Browser.</p>
<p>Don’t forget to open the 3000 port in the Security Group</p>
<pre><code class="lang-plaintext">&lt;Public-ip:3000&gt;
</code></pre>
<p>Output</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699506627834/248f2f9c-f58d-4c3f-8590-cc06133dfede.png?auto=compress,format&amp;format=webp" alt /></p>
<h3 id="heading-step-8-termination">Step 8: Termination</h3>
<ol>
<li><p>Delete the personal Access token of the docker.</p>
</li>
<li><p>Delete the containers.</p>
<pre><code class="lang-plaintext"> docker stop &lt;container name&gt;
 docker rm &lt;container name&gt;
</code></pre>
</li>
<li><p>Delete the Ec2 instance.</p>
</li>
</ol>
<p>And there you have it, folks! You’re now the DevOps master of your YouTube app deployment. We’ve journeyed through code, quality, security, containers, and automation, all with GitLab. Now it’s your turn to unleash the power of DevOps and take your YouTube app to the next level!</p>
<p>So, what’s next on your development adventure? Whether it’s conquering new projects, exploring even cooler tech, or simply celebrating with a well-deserved coffee break, remember that DevOps is all about making your life easier and your code better. Embrace the joy of seamless deployments, keep learning, and never stop having fun in the ever-evolving world of software development. 🚀😎</p>
]]></content:encoded></item></channel></rss>