11- Jenkins: Build Docker Images and Push to DockerHub
Our current goal is to create a new Jenkins pipeline that clones our github repo to jenkins workspace and build docker images that are defined in docker-compose.yml file by using docker compose commands in the jenkinsfile. After these images are built, they are going to be pushed to their corresponding DockerHub repositories.
My current docker-compose.yml file does not build an image for postgres but it download the postgresql docker image from dokcer hub and it runs the container on the host machine. When we use docker build command in Jenkins pipeline, it automatically adds jenkins job name in front of the image name.
<jenkins-job-name>servicename:tag (for example website_ci-app:latest, website_ci-nginx:latest or website_ci-db:latest)
To be able to push these images to DockerHub. Images has to be tagged again according to repo names in DockerHub (selimica/website-app:version)
If Jenkins file does not find an postgres image in its workspace, it will give an error something like: Error response from daemon: No such image
Therefore, first I need to modify docker-compose.yml file to build a postgresql image.
Modify db service from this:
To that:
Save docker-compose.yml file. Then create a folder named postgres in website folder. Create a dockerfile in that postgres folder. Add the below line in to that dockerfile. So, docker-compose will build an image just like app and nginx images.
FROM postgres:15.1-alpine
Now create 3 new repositories in DockerHub. Each image will be kept in different repos. I named the new repos like below.
Then I modified jenkinsfile in website folder with the content below. Each Stage is already explained in the file.
pipeline{
agent any
environment{
DOCKERHUB_CREDENTIALS = credentials('DockerHub')
JOB_NAME= "website_ci"
IMAGE_TAG= "$BUILD_NUMBER"
DOCKERHUB_USERNAME= "selimica"
IMAGE_NAME= "website-app"
}
stages{
stage('Cleanup Workspace'){
steps{
script{
cleanWs()
}
}
}
stage('Checkout SCM'){
steps{
script{
git credentialsId: 'GitHub',
url: 'https://github.com/selimatmaca/website.git',
branch: 'main'
}
}
}
stage('Build Docker Images and tag them for DockerHub repos'){
steps{
sh 'docker compose build'
//sh 'docker compose up -d'
sh 'docker images'
sh 'docker tag $JOB_NAME-app:latest selimica/website-app:latest'
sh 'docker tag $JOB_NAME-nginx:latest selimica/website-nginx:latest'
sh 'docker tag $JOB_NAME-app:latest selimica/website-app:$BUILD_NUMBER'
sh 'docker tag $JOB_NAME-nginx:latest selimica/website-nginx:$BUILD_NUMBER'
sh 'docker tag $JOB_NAME-db:latest selimica/website-postgres:latest'
sh 'docker tag $JOB_NAME-db:latest selimica/website-postgres:$BUILD_NUMBER'
}
}
stage('Push Docker Images'){
steps{
sh 'echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin'
echo 'Login completed'
sh 'docker push selimica/website-app:$BUILD_NUMBER'
sh 'docker push selimica/website-nginx:$BUILD_NUMBER'
sh 'docker push selimica/website-app:latest'
sh 'docker push selimica/website-nginx:latest'
sh 'docker push selimica/website-postgres:latest'
sh 'docker push selimica/website-postgres:$BUILD_NUMBER'
}
}
stage('Delete Docker Image From Jenkins'){
steps{
script{
sh "docker rmi selimica/website-app:$BUILD_NUMBER"
sh "docker rmi selimica/website-nginx:$BUILD_NUMBER"
sh "docker rmi selimica/website-postgres:$BUILD_NUMBER"
sh "docker rmi selimica/website-app:latest"
sh "docker rmi selimica/website-nginx:latest"
sh "docker rmi selimica/website-postgres:latest"
}
}
}
}
//Stages are completed.
//Log Out!
post{
always{
sh 'docker logout'
}
}
}
Commit and Push to Git
git add .
git commit -m "jenkinsfile changed"
git push
On VSCode, Ctrl + Shift + P and run Jenkins Pipeline. Note that we are running pipeline manually at this point. We will automate all these later.
By using settings.json, VSCode triggers the pipeline named "website_CI".
Jenkins first cleans up the workspace. Then it fetches the files and folders from GitHub. Docker compose builds the images according to the docker-compose.yml which resides in the workspace. Then local images in workspace are tagged according to DockerHub repos. Finally we push the images to the correct DockerHub repos.
After Jenkins displayed success message, I checked DockerHub repos and saw each repo has its images like this. Number 2 and 3 are the Jenkins build numbers. Everytime I run this Jenkins pipeline, it will build and push a new image to each repo with the new build number and it overwrites the latest tagged image.
GitHub Webhook:
We can use GitHub webhook to run jenkins jobs automatically. Let's say a developer changes some codes on his local machine and commits and pushes to github. By using webhook we can tell Jenkins server that there is a code change and jenkins job should be triggered automatically. We need github plugin on our Jenkins server, wehave already installed that. Log on to your jenkins server > Manage Jenkins > System > Scroll down to GitHub > Click Advanced > click the checkbox "Specify another hook URL for GitHub configuration" and copy the url. We just need to copy that url. Don't save anything on this page.
Log on to your GitHub account and choose your repository > Settings > Webhooks > Add Webhook
Enter the url you copied from jenkins server, choose Content type as json and click Add Webhook button.
Now go back to your Jenkins server and choose the jenkins job > Configure > Scroll down to "Build Triggers" > Check "GitHub hook trigger for GITScm polling" and Save.
Now I am going to test if webhook works properly. On my local machine, I just created a test filenamed "webhooktest.txt" and then used git commands to commit and push.
On jenkins server, my jenkins job started automatically. Git repo cloned, images are created and pushed to DockerHub.
I guess that we completed Jenkins part for our project (at least for now). In the next article, we will create a Kubernetes cluster on DigitalOcean.
- Hits: 193