CI/CD pipeline using Jenkins and Docker
Tags: jenkins, docker
Published: 2024-07-02 11:11:53

Today we will be creating a CI/CD pipeline in Jenkins which fetches code from github and creates an image from Dockerfile and runs our app in a docker container and terminates automatically after scheduled time


####1. Creating EC2 instances
I have used AWS EC2 to launch an ubuntu instance which comes under free tier you can try it on your local machine or use a VM from any public cloud provider

![EC2 Instance Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6rs703urr1pqnng7xnj.png)

Now connect to the instance

####2. Setting up Jenkins & Docker
We need to update our installation package manager

```
$ sudo apt update
```
Jenkins needs java to run so we'll proceed with installing Java first

```
$ sudo apt install openjdk-11-jre
```

Check if java is installed correctly
![Check java](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dipsd0mvfmvxvszq5bxf.png)

Now we download Jenkins using curl command
```
$ curl -fsSL https://pkg.jenkins.io/debian/jenkins.io.key | sudo tee \   /usr/share/keyrings/jenkins-keyring.asc > /dev/null
```

We add it to our package manager
```
$ echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \   https://pkg.jenkins.io/debian binary/ | sudo tee \   /etc/apt/sources.list.d/jenkins.list > /dev/null
```
Lets update our package manager once
```
$ sudo apt-get update
```

Now install jenkins
```
$ sudo apt-get install jenkins
```

Before we can use jenkins we need to enable it first
```
$ sudo systemctl enable jenkins
```

Start jenkins server
```
$ sudo systemctl start jenkins
```

Check status of jenkins 
```
$ sudo systemctl status jenkins
```

You would get a response like this
![jenkins status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wru7u5t7zhup64oyctu7.png)

Jenkins runs on port 8080 by default go to localhost:8080 to access it.
Since I have a VM provisioned in the cloud I need to open port 8080 to allow connections
I went to Network security groups and added the port number I want to access.

![NSG in AWS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e5ar33t1frvzuk2u0g57.png)

Since I don't want everyone to able to access jenkins I have limited the port to only a single host


Now when I login to port 8080 I am greeted with a login screen of jenkins

![Jenkins login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khckflzo6gcv836ebn9c.png)

Now to login we need credentials
Username is admin
password can be found through the following command
```
$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword
```

After logging into jenkins change your password and jenkins would ask to install plugins let it install them

Now we are greeted with a screen like this click on new item
![Jenkins Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8w5ms7axjii0rmxmscuf.png)


Since I plan to keep it simple click on freestyle project 
![Setting up](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ziatwihgnqiyhjjkqtff.png)

After adding the name for you app add your github repo you want to connect
![Git repo adding](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btr7itvjlm0f9x5psrx9.png)

After adding a repo we need to tell jenkins how to access the repo and give it required permission so it can fetch the code from repo
To achieve this I have used SSH keys simple generate a ssh key and add the public key in github

![Credentials for Github](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/muf4wtrbqotf10xobkeu.png)

Now we need to add private key in jenkins so that it can authenticate with github and pull code from our repo.
Click on add below credentials and choose Jenkins 

![SSH Private key adding image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d1cpdvtsgvjnmcvdyz36.png)

Give a name to you credential and add the private key
![Naming credential](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kay8lc5o6keddujth0j7.png)

Before we move to next step install a plugin called Github Integration available in Jenkins you can do this by going to manage jenkins and selecting plugins and search for the extension

Now add the steps to build the app and run it. Since our app runs on node.js I will be using a docker container. I have created a Dockerfile 
to do this.
I am using shell scripting to run the container in a shell and exit it 
![Shell Script](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pcw2vt3m2wjiq569vo1p.png)

The commands in above image do the following things:
* Build the docker image
* Run the app in a container on port 8000
* The app will be live for 5 minutes
* After that the container is stopped and removed from the machine 

The Build ID with a $ is an environment variable which changes according to build of jenkins so we get a new container on every run and there won't be any problems as we won't be running same container everytime

Click Save when done

We need docker to run the app if you don't have install it on your machine 
```
$ sudo apt install docker.io 
```

We also need a Dockerfile 
You can find it on my repository [here](https://github.com/pankaj892/node-jenkins-cicd/blob/main/Dockerfile)

Dockerfile does the following:
* It pulls the latest node image from DockerHub
* The work directory is set as app 
* It runs npm install and all libraries and packages are downloaded
* It exposes port 8000 for our app
* It runs the command `node app.js` in a shell

Lets move on to next stage

####3. Configuring Github
We need to make sure that when a change is detected in our repo jenkins runs the pipeline automatically we use webhooks to achieve this 

Go to Settings > Webhooks for your repo not your account 
![Webhook Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5e7c0661e1isf2s4ptzm.png)

Now add url of your jenkins where it is hosted followed by /github-webhook/ and click on save 
![Webhook details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ue1k1of30sqdqla4kbj6.png)

####4. Testing our app
Now lets do a dry run and see if our pipeline works as expected

Click on build now to run the pipeline 
![Dry Run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jcmr8d4g8c5p3mtdnqq5.png)

Build has started 
![Pipeline status](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxld0mza4k4e0i5xpxvg.png)

I expect the container name to end with build number let's check
![Container name checking](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/42x7v9cf5gq25deq5qsm.png)
It is working as expected

And pipeline is successful since we can see our app
![Pipeline success](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d44bdjcvio5g9ufhphm5.png)

Now lets change something in repo and see if jenkins picks it up and runs the pipeline 
I changed the background and some text 

![Pipeline with changes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1h29eisowo97khh1gc1i.png)
It is working as expected


We have completed this project successfully

If you have any questions comment down below I'll be happy to help