Devops-task2:- Integration of Jenkins with Docker and Git.
Anshu Jhalani
Senior Software Engineer at "In Time Tec" || Backend Developer || .NET Core || .NET Framework || C# || MVC || SQL SERVER || REST Web Services || LINQ || JavaScript || JQuery || Docker Certified
Problem Statement -
1. Create a container image that’s has Jenkins installed using Dockerfile.
2. When we launch this image, it should automatically start the Jenkins service in the container.
3. Create a job chain of job1, job2, job3 and job4 using the build pipeline plugin in Jenkins.
4. Job1: Pull the GitHub repo automatically when some developers push the repo to GitHub.
5. Job2: By looking at the code or program file, Jenkins should automatically start the respective language interpreter install image container to deploy code ( eg. If code is of PHP, then Jenkins should start the container that has PHP already installed ).
6. Job3: Test your app if it is working or not.
7. Job4: If the app is not working, then send an email to the developer with error messages.
8. Create One extra job job5 for monitor: If the container where the app is running. fails due to any reason then this job should automatically start the container again.
SOLUTION -
Prerequisite :
- GitHub Account
- git on local system.
- Docker and docker images for creating environment like for Apache web-server or httpd. Make sure docker service must start.
If you have any doubt about setting up requirement then refer to my following article.
STEP 1: First we create a GitHub repository devops-task2-git-docker-jenkins with checking on README.md file and Clone this repository into local system using git.
git clone https://github.com/ajtechy/devops-task2-git-docker-jenkins.git
STEP 2: Now we will configure a post-commit hook. As soon as developer commit code it will automatically push to GitHub.
touch .git/hooks/post-commit chmod +x .git/hooks/post-commit vi .git/hooks/post-commit
STEP 3: we will add following code to it.
#!/bin/bash current_branch=$(git branch --show-current) if [ $current_branch == "dev" ] then echo "dev branch" git push -u origin dev else echo" master branch" git push -u origin master fi
STEP 4: We create a Tunneling for jenkins port 8080 so that we can set web hook over github. Command to start Tunneling
./ngrok http 8080
This command will show following output with public url .
ngrok by @inconshreveable (Ctrl+C to quit) Session Status online Session Expires 7 hours, 56 minutes Web Interface https://127.0.0.1:4040 Forwarding https://2798f2d4fd51.ngrok.io https://localhost:8080 Forwarding https://2798f2d4fd51.ngrok.io https://localhost:8080
STEP 5: We will also add web hook to the repository which will tell whenever a new commit is pushed to the repository.
repository >> Setting >> Webhooks >> add new.
STEP 6: we will start by creating a Dockerfile using centos: latest image pulled from docker hub.
Explaination of dockerfile
- FROM: the image to be used for launching container
- RUN: commands to be executed while building the modified container
- COPY: command will be used to copy files from host to image while building it.
- CMD: will keep the Jenkins live till the container is on and will start on container boot.
To build the image we use following command.
docker build -t jenkins:latest .
here *. can be replaced with the path of Dockerfile.
After building Dockerfile we launch container using following command.
docker run -dit --name jenkins --hostname=JENKINS --privileged -p 32760:8080 -v /:/host jenkins:latest
--privileged has been used for special access when we use run any docker command inside container.
-v has been used to mount root to host directory inside container . After mounting we can run any root command inside container using chroot command. Here i use the follownig command to switch the root to that of host os and run all the commands their and after running the required commands I switched back to the container.
chroot /host /bin/bash <<"EOT" #write all required command to be run EOT
Now we move on to our jobs.
JOB 1:
This job will Pull the GitHub repo automatically when some developers push the WebApp code to GitHub. This job is triggered by github-webhook i.e. when developers pushes new code to GitHub this job will be triggered.
JOB 2:
This job will be triggered as soon as Job1 completes. This job will do multiple things.
- First of all , this job will check which language is used in our code then accordingly run the environment on the host system. If code is of PHP, then Jenkins should start the container that has PHP already installed .
- If our environment is already running then this job will only copy our new code in that environment.
Here i use container for Html or PHP according to developer code. we can add more according to requirement.
chroot /host /bin/bash <<"EOT" dir=/devops-task2/devops-task2-pull-code/ if [[ -n $(ls $dir | grep html) ]] then if ! docker ps -a | grep html_container then echo "launch" docker run -dit -p 8083:80 -v /devops-task2/devops-task2-pull-code:/var/www/html --name html_container httpd:v1 elif ! docker ps | grep html_container | grep up then echo "start" docker start html_container fi elif [[ -n $(ls $dir | grep php) ]] then if ! docker ps -a | grep php_container then docker run -dit -p 8084:80 -v /devops-task2/devops-task2-pull-code:/var/www/html --name php_container apache:v1 elif ! docker ps | grep php_container | grep up then docker start php_container fi fi EOT
JOB 3:
This job will be triggered as soon as Job2 completes and test our web server whether it is working or not . If it is not working then this job will be successful and trigger next job to notify the developer via mail.
If our web server is working properly then this job will fail intentionally , so that next job will not triggered.
chroot /host /bin/bash <<"EOT" for file in $(sudo ls /devops-task2/devops-task2-pull-code/) do if [[ -n $(echo $file | grep html) ]] then export port=$(sudo docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}' html_container) export status_code=$(sudo curl -o /dev/null/ -s -w "%{http_code}" 192.168.43.240:$port/$file) echo $status_code $file $port if [[ $status_code == 200 ]] then echo -e "Everything is alright.\nwebserver is running good" else echo -e "Something is wrong" # if something is wrong then this job will notify via email and also trigger to notify-mail job. exit 0 #exit 0 means seccess of this job fi elif [[ -n $(echo $file | grep php) ]] then export port=$(sudo docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}' php_container) export status_code=$(sudo curl -o /dev/null/ -s -w "%{http_code}" 192.168.43.240:$port/$file) if [[ $status_code == 200 ]] then echo -e "Everything is alright.\nwebserver is running good" else echo -e "Something is wrong" # if something is wrong then this job will notify via email and also trigger to notify-mail job. exit 0 #exit 0 means seccess of this job fi fi done # if Everyrhing is good then this job will not notify via email and also not trigger to notify-mail job. exit 1 #exit 1 means failure of this job EOT
JOB 4:
This job will only be triggered when Job3 success . Success of Job3 means our web server is not working properly due to some issue. In this situation this job will send notification to developer via mail to solve the issue in the website and push updated code on GitHub.
Here is my python code to send mail to developer.
JOB 5:
This job will keep monitoring every hour on our container and web server. Here i use Build periodically trigger using crontab syntax. If container goes down it automatically start container or launch new container .
chroot /host /bin/bash <<"EOT" dir=/devops-task2/devops-task2-pull-code/ for file in $(sudo ls /devops-task2/devops-task2-pull-code/) do if [[ -n $(ls $dir | grep html) ]] then if docker ps -a | grep html_container | grep Up then echo "UP" export port=$(sudo docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}' html_container) export status_code=$(sudo curl -o /dev/null/ -s -w "%{http_code}" 192.168.43.240:$port/$file) if [[ $status_code == 200 ]] then exit 0 else docker rm -f html_container docker run -dit -p 8083:80 -v /devops-task2/devops-task2-pull-code:/var/www/html --name html_container httpd:v1 fi else echo "start" docker start html_container fi elif [[ -n $(ls $dir | grep php) ]] then if docker ps -a | grep php_container | grep Up then echo "UP" export port=$(sudo docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{(index $conf 0).HostPort}}{{end}}' php_container) export status_code=$(sudo curl -o /dev/null/ -s -w "%{http_code}" 192.168.43.240:$port/$file) if [[ $status_code == 200 ]] then exit 0 else docker rm -f php_container docker run -dit -p 8083:80 -v /devops-task2/devops-task2-pull-code:/var/www/html --name php_container apache:v1 fi else echo "start" docker start php_container fi fi done EOT
Build pipeline looks like this.
Finally our web page looks like this.
Finally all the steps are done . I hope you enjoy this.
DevOps Engineer |SAA-C03 | RHCSA Certified | Ansible Certified l ACE in GCP
4 年Superb Guy ! I Appericate your constant hardwork, ?? may you have great journey a head :)