"Starbucks Clone Reimagined: Automated & Secure Deployment with Jenkins, Docker, SonarQube and GitHub"


This blog post will guide you through setting up a CI/CD pipeline for a (Starbucks) Nodejs application, streamlining the build, deployment, and integration process. Using Jenkins, Docker, and GitHub, we'll automate every step, ensuring efficient and reliable software delivery.
Repository for this Project:
Project Overview
This project involves creating a complete CI/CD pipeline that automates the deployment of a (starbucks) Nodejs application. Here are the steps we will follow:
Create AWS EC2 Instances to host Jenkins and Docker.
Set up Jenkins to automate the CI/CD pipeline.
Containerize the Nodej application using Docker.
Create a Jenkinsfile for automated builds and deployment.
Techstack used in this project :
GitHub
SonarQube
Trivy
Docker
Email
Steps to Implement the Project
Step 1: Create An AWS EC2 Instance
We'll start by setting up an instance:
Log in to AWS:
- Go to the AWS Console and log in.
Launch an EC2 Instance (Jenkins-server):
Go to the EC2 Dashboard and click on Launch Instance.
Select the Ubuntu 24.04 LTS AMI.
Choose t2.medium for the Jenkins Master instance.
Configure Security Group:
SSH (port 22) for remote access.
HTTP (port 80) to access Jenkins through the browser.
Click Review and Launch.
Step 2: assign an Elastic IP (EIP) to a Jenkins server on AWS,
follow these steps:
Allocate an Elastic IP
Go to the EC2️ Dashboard in AWS Management Console.
Under Network & Security, click Elastic IPs.
Click Allocate new address and choose your region.
Associate Elastic IP with Jenkins Server:
o In the Elastic IPs section, select the allocated EIP.
o Click Actions, then Associate Elastic IP address.
o Select the Jenkins server instance (EC2 instance) and click Associate.
Verify Association:
Check if the EIP is now associated with the Jenkins EC2 instance.
Ensure Jenkins is accessible via the new IP.
Benefits:
Static IP: Provides a fixed IP address that won't change even if you stop/start your EC2 instance. •
Easy Access: Direct and consistent access to Jenkins from external networks.
High Availability: In case of instance failure, the EIP can be reassigned to a new instance quickly.
Step 3 : Install the required Tools
SSH into instance using below command:
Update EC2 Instance
Ensure Ec2 instance are up to date by running:
ssh -i <your-key>.pem ubuntu@<your-ec2-public-ip>
sudo apt update && sudo apt upgrade -y
Install Java on EC2 Instance
Jenkins requires Java, so install OpenJDK 17 on each instance:
apt install openjdk-17-jre -y
java -version
Install Jenkins
we are going to build and deploy the application on jenkin-server, so no need to install the jenkins server on Ec2 machine
create a bash script with jenkins.sh and provide the executable permisssions to it
(Reference URL for commands: https://www.jenkins.io/doc/book/installing/linux/#debianubuntu)
#!/bin/bash
#this Script belong to Cloudaseem Youtube channel #####
# jenkins installation on ubuntu
sudo apt update -y
sudo apt install fontconfig openjdk-17-jre -y
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update -y
sudo apt-get install jenkins -y
sudo systemctl enable jenkins
sudo systemctl start jenkins
# Verifiy Jenkins installation: jenkins --version
# Open Port No. 8080 for VM and access Jenkins
# Setup Jenkins by following the necessary steps
Install Docker
create a bash script with docker.sh and provide the executable permisssions to it
#!/bin/bash
# Script to install Docker on an EC2 instance and configure permissions
# Update the package list
sudo apt-get update -y
# Install Docker
sudo apt-get install docker.io -y
# Add the 'ubuntu' and 'jenkins' users to the 'docker' group to allow running Docker without sudo
sudo usermod -aG docker ubuntu
sudo usermod -aG docker jenkins
# Apply the new group settings immediately
newgrp docker
# Set correct permissions for the Docker socket to allow 'docker' group members to access it
sudo chmod 660 /var/run/docker.sock
sudo chown root:docker /var/run/docker.sock
# Restart Docker service to apply changes
sudo systemctl restart docker
# Verify installation
docker -version
Install Trivy
Trivy is an open-source vulnerability scanner for containers and other artifacts, such as Kubernetes manifests. It can detect vulnerabilities in OS packages and application dependencies, ensuring your deployments are secure and compliant.
Why Use Trivy?
• Comprehensive Scanning: Scans containers, filesystems, and repositories for vulnerabilities.
• Ease of Use: Simple installation and easy-to-understand output.
• Integration: Can be integrated into CI/CD pipelines for continuous security.
Install Trivy
#!/bin/bash
# Script to install Trivy on an instance
# Install necessary dependencies
sudo apt-get install wget apt-transport-https gnupg lsb-release -y
# Add the Trivy repository key
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
# Add the Trivy repository to the sources list
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
# Update package lists
sudo apt-get update -y
# Install Trivy
sudo apt-get install trivy -y
Step 4: Access the jenkins and do the following configuration and add credentails and add tools for necessary things
Access Jenkins in your browser:
http://<Elastic-ip>:8080
Unlock Jenkins using an administrative password and install the suggested plugins. Retrieve the initial admin password:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Create a user click on save and continue.
Jenkins Getting Started Screen.
Follow the setup wizard and install recommended plugins
Install Plugins like JDK, SonarQube Scanner, NodeJs,
Check Goto Manage Jenkins →Plugins → Available Plugins → Install below plugins
1. Eclipse Temurin Installer (Install without restart)
2. SonarQube Scanner (Install without restart)
3. NodeJs Plugin (Install Without restart) – 16.20.2
4. Stage view
5. jdk
Docker plugin
6. Docker
7. Docker Commons
8. Docker Pipeline
9. Docker API
10. docker-build-step
Create a Gmail SMTP App Password
An App Password is a 16-character password that allows third-party applications (like Jenkins) to send emails using Gmail SMTP securely.
Step 1️: Enable 2️-Step Verification
Before generating an App Password, you must enable 2️-Step Verification in your Google Account.
Go to Google Account Security: Google My Account
Scroll to "Signing in to Google".
Click "2️-Step Verification" → Click "Get Started".
Follow the steps to set up 2️-Step Verification (via SMS or Authenticator App).
Step 2️: Generate an App Password
Go to App Passwords Page: Google App Passwords
Sign in with your Google Account.
Under "Select app", choose "Mail".
Under "Select device", choose "Other (Custom Name)" and enter "Jenkins SMTP".
Click "Generate".
Copy the 1️6-character App Password (e.g., abcd efgh ijkl mnop).
Add credentials as Username and password in jenkins
Step 3: Configure Gmail SMTP in Jenkins
Go to Jenkins Dashboard → Manage Jenkins → Configure System.
Scroll to "E-mail Notification".
Set the following:
SMTP Server: smtp.gmail.com
Use SMTP Authentication: Checked
User Name: Your Gmail ID (your-email@gmail.com)
Password: Paste the App Password
SMTP Port: 587
Use TLS:
Click Save.
scroll Extended Email Notification
Set the following:
SMTP Server: smtp.gmail.com
SMTP Port: 465 (for tls)
Use SSL: Checked
configure tools and credentials:
Set Up Docker Hub Credentials in Jenkins
Go to Manage Jenkins > Security > Credentials > System > Global credentials (unrestricted) and click Add Credentials.
Set Kind to Username with password.
Add your Docker Hub username and password and save , for password generate Personal Access Token on DockerHub.
configure SonarQube Credentials
install sonarqube in another ec2 server and configure with jenkins
create a server with named sonar-server
Install the docker and create a sonarqube container
docker run -d --name sonar -p 9000:9000 sonarqube:lts-community
Access the application with <public-ip:9000>
update the sonarqube password
Tha Dashboard of sonarqube
Create Sonar token in order to connect with Jenkins
Click on Administration → Security → Click on Tokens and Update Token → Give it a name → and click on Generate Token
Add these generated token in jenkins Credentials like below
manage jenkins → credentials → add like below
To connect jenkins with SonarQube → add system configuarations in Jenkins
manage jenkins → system → ADD SonarQube
to connect SonarQube with jenkins → make sure enable webhooks in SonarQube
Administration → Webhooks
Global Tool Configuration:
add Jdk as a global tool as below
as Nodejs
add sonar-qube
Step 5: shared library in jenkins :
A shared library in Jenkins is a collection of Groovy scripts shared between different Jenkins jobs. To run the scripts, they are pulled into a Jenkinsfile.
Each shared library requires users to define a name and a method of retrieving source code. These methods include local files, Git repositories, and Jenkins SCM plugins.
Developers use shared libraries to avoid writing the same code from scratch for multiple projects. Shared libraries share code across development projects, thus optimizing the software development life cycle. This drastically cuts down time spent on coding and helps avoid duplicate code.
to access a shared library from Jenkins male sure to add those GitHub repos into jenkins as shown in below
step 1: create a credentials for GitHub as shown in below
Create a Shared Library Repository
Create a GitHub Repository:
Go to GitHub and create a new repository.
Name it something like
Jenkins-shared-library
set it to Public or Private (based on your needs), and click Create Repository.
Clone the Repository:
Clone the repository to your local machine:
https://github.com/Saiprasad-1727/Jenkins-shared-library.git
and add the groovy scripts as follows which we are going to use in declarative pipeline
clone.groovy
Handles code cloning from a Git repository:
def call(String url, String branch){ git url:url , branch:branch }
dockerbuild.groovy
Builds a Docker image:
def call(String imageName, String imageTag){ sh "docker build -t ${imageName}:${imageTag} ." }
dockerpush.groovy
Pushes a Docker image to Docker Hub:
def call(String credId, String imageName,String imageTag){ withCredentials([usernamePassword(credentialsId:credId, usernameVariable:"dockerHubUser", passwordVariable:"dockerHubPass")]){ sh "docker login -u ${env.dockerHubUser} -p ${env.dockerHubPass}" sh "docker image tag ${imageName}:${imageTag} ${env.dockerHubUser}/${imageName}:${imageTag}" sh "docker push ${env.dockerHubUser}/${imageName}:${imageTag}" } }
deploy.groovy
Deploys a Docker container:
def call(){ sh "docker-compose down && docker-compose up -d" }
Configure the Shared Library in Jenkins
Access Jenkins:
- Go to Manage Jenkins > Configure System.
Add Global Pipeline Library:
Scroll to Global Pipeline Libraries and click Add.
Fill in the details:
Name:
Jenkins-shared-library
(matches@Library('Jenkins-shared-library')
in yourJenkinsfile
).Default Version:
main
.Retrieval Method:
Modern SCM
.Source Code Management:
Select Git.
Add the repository URL:
Copy
Copy
https://github.com/Saiprasad-1727/Jenkins-shared-library.git
Add credentials if required (e.g., GitHub token or SSH key).
Save Configuration:
- Click Save.
step 6: Create the jenkins pipeline for continious integration and deployment
jenkins > new item > Enter an item name as starbucks
> select pipeline
option and ok
write the description as per your wish
go to pipeline option on left side and start writing declarative pipeline for ci/cd as below
@Library('jenkins_shared_library') _
pipeline {
agent any
tools{
jdk 'jdk'
nodejs 'node17'
}
environment {
SCANNER_HOME=tool 'sonar-scanner'
}
stages {
stage('clean workspace'){
steps{
cleanWs()
}
}
stage("checkout from Git") {
steps {
git branch: 'main', url: 'https://github.com/Saiprasad-1727/kubernetes-project-starbucks.app.git'
}
}
stage("Sonarqube Analysis "){
steps{
withSonarQubeEnv('SonarQube') {
sh ''' $SCANNER_HOME/bin/sonar-scanner -Dsonar.projectName=starbucks \
-Dsonar.projectKey=starbucks '''
}
}
}
stage("quality gate"){
steps {
script {
waitForQualityGate abortPipeline: false, credentialsId: 'Sonar-token'
}
}
}
stage('Install Dependencies') {
steps {
sh "npm install"
}
}
stage('TRIVY FS SCAN') {
steps {
sh "trivy fs . > trivyfs.txt"
}
}
stage('building the image'){
steps{
dockerbuild("starbucks","latest")
}
}
stage('push image to hub'){
steps{
dockerpush("dockerHubCred","starbucks","latest")
}
}
stage("TRIVY"){
steps{
sh "trivy image saiprasad1727/starbucks:latest > trivyimage.txt"
}
}
stage('App Deploy to Docker container'){
steps{
sh 'docker run -d --name starbucks -p 3000:3000 saiprasad1727/starbucks:latest'
}
}
}
post {
always {
emailext attachLog: true,
subject: "'${currentBuild.result}'",
body: """
<html>
<body>
<div style="background-color: #FFA07A; padding: 10px; margin-bottom: 10px;">
<p style="color: white; font-weight: bold;">Project: ${env.JOB_NAME}</p>
</div>
<div style="background-color: #90EE90; padding: 10px; margin-bottom: 10px;">
<p style="color: white; font-weight: bold;">Build Number: ${env.BUILD_NUMBER}</p>
</div>
<div style="background-color: #87CEEB; padding: 10px; margin-bottom: 10px;">
<p style="color: white; font-weight: bold;">URL: ${env.BUILD_URL}</p>
</div>
</body>
</html>
""",
to: 'annam.saiprasad2709@gmail.com',
mimeType: 'text/html',
attachmentsPattern: 'trivy.txt'
}
}
}
Click on Build Now and check the stage view, if any stage got error click on builds and the check the console output and verify the errors and try to correct the pipeline and any configuration.
Final output
Access the application with <public-ip:3000>
Conclusion
By following these steps, we have successfully set up a CI/CD pipeline to automate the deployment of your Starbucks Application using Jenkins, GitHub, and Docker, shared libraries,etc. This setup not only simplifies the deployment process but also enhances productivity.
Before you leave
If you enjoy the content I share, feel free to connect with me on Sai Prasad Annam there’s a lot more to explore, and I think you’ll find it intriguing!"
And feel free check out my devops projects publication Dashboard - Overview
Subscribe to my newsletter
Read articles from SAI PRASAD ANNAM directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

SAI PRASAD ANNAM
SAI PRASAD ANNAM
Hi there! I'm Sai Prasad Annam, an enthusiastic and aspiring DevOps engineer and Cloud engineer with a passion for integrating development and operations to create seamless, efficient, and automated workflows. I'm driven by the challenges of modern software development and am dedicated to continuous learning and improvement in the DevOps field.