Simple Jenkins Declarative Pipeline to Push Docker Image To Docker Hub

Docker hub is one of the many popular repositories for storing docker images.
In this post we will cover how to create a docker image using Dockerfile with Jenkins pipeline. Once we have built the image, we will login to Docker Hub and push the image to our private repo in the docker hub.

Without further ado let us dive right in. 

Create a Jenkins Pipeline Project


For our example, we will create a Jenkins declarative pipeline. We will write the code as we move along. You can also refer to complete pipeline code mentioned towards the end of the post. 

Build the Pipeline


Checkout latest code from Github  

First of all, we will need to checkout the code from the repository which in our case is Github.

stage("Git Checkout"){  
    steps{     
	git credentialsId: 'github', url: 'https://github.com/githubusername/githubreponame'
	echo 'Git Checkout Completed'   
    }
}

In our configuration for github credentials in Jenkins, we have named github as the credentialsId.

In the URL, githubusername should be replaced with your username in github

Similarly githubreponame should be replaced with the name of your repo in github.


Build docker image using Dockerfile

Once we have checked out the code, we will go ahead and build the docker image.

For our example we are assuming that the code has been built and an executable (.war file in our case) has been created as part of a previous workflow.

Now, to build the docker image, we will need a dockerfile.

Dockerfile

Dockerfile contains all the commands required to assemble a docker image using docker build command. 

The dockerfile that we will use to build an image has the following content. We will take tomcat as the base image from Docker Hub, copy the .war file in a webapps folder inside our docker container and run the tomcat server.

FROM tomcat
USER root
COPY  ProjectDockerImage.war /usr/local/tomcat/webapps/
CMD ["catalina.sh","run"]


We have named our file with the default name of Dockerfile. The default location for Dockerfile is the main project folder.

Incase we intend to change the name or location of Dockerfile, we should build the image with a – f flag and mention the complete path to dockerfile.

Build Docker Image

Build image with – t flag to tag the image. BUILD_NUMBER is an environment variable whose value is available to jenkins jobs. This can be used to tag the docker image. This way we will have a unique number tagged to the image everytime a new image is build. Also the image can be easily traced to the build number.

stage('Build Docker Image') {  
    steps{                     
	sh 'sudo docker build -t <dockerhubusername>/<dockerhubreponame>:$BUILD_NUMBER .'     
	echo 'Build Image Completed'                
    }           
} 
    

Steps for Logging in to Docker Hub

We will follow the following steps in order to login to Docker Hub from Jenkins pipeline :


1. Create personal access token in Docker Hub.


2. Create Docker Hub credentials in Jenkins


3. Store the credentials as an environment variable in Jenkins pipeline


4. Login to the Docker Hub with the credentials via a shell command

Step1: Create a personal access token in Docker Hub

To create a personal access token in Docker Hub, login to your account in Docker Hub and from the top right select <dockerhub username> –> My Account. From the My Account page as shown below in the screenshot, select Security from the left side bar. Then select New Access Token on the right side.

Screenshot: Create a personal access token in Docker Hub

You will need to provide the token description by which you will be able to refer to it. Keep the value of the token safe with you as it will be displayed only once.


Step 2: Store credentials for Docker Hub in Jenkins


Within Jenkins UI, we will go to Manage Jenkins-> Manage Credentials and create new credentials with username, password.
We need to provide the username for our Docker Hub account. In the password area, you can either provide your Docker Hub password or create a personal access token in Docker Hub as explained above and provide its value in the password area. Then we need to provide an id for the credentials. We have mentioned the id as dockerhubcredentials.

Step 3: Set environment variable in Jenkins Pipeline

We will store the Docker Hub credentials in an environment variable DOCKERHUB_CREDENTIALS in the jenkins pipeline.

environment {     
    DOCKERHUB_CREDENTIALS= credentials('dockerhubcredentials')     
} 


  where dockerhubcredentials is the id used when defining the Docker Hub credentials in Jenkins.

The Jenkins declarative pipeline is provided with a helper method called credentials(). When the username and pssword credentials are stored in the environment variable using the credentials method, these credentials can be accessed as a set of username password from the environment variable which is DOCKERHUB_CREDENTIALS in our case.

Apart from this, this environment variable can also be used to access username as a separate entity by appending USR to the environment variable i.e. DOCKERHUB_CREDENTIALS_USR in our case. The same variable can also be used to access password by appending PSW to the environment variable i.e. DOCKERHUB_CREDENTIALS_PSW in our case.

Jenkins documentation describes the approach for using credentials as environment variable in Jenkins declarative pipeline.

Step 4: Login to DockerHub

Once we have setup the credentials as shown above, we can login to the Docker Hub with the following stage in Jenkins pipeline    

stage('Login to Docker Hub') {      	
steps{                       
sh 'echo $DOCKERHUB_CREDENTIALS_PSW | sudo docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin'                
echo 'Login Completed'   
}           

The reason for using –password-stdin is to prevent the password from ending up in the shell’s history, or log-files. You can refer to the docker documentation for more details.

Push Image to Docker Hub

Once we have logged in, we just need to push the docker image that we had built to Docker Hub. We will push the image with the same tag with which we had built the image.

stage('Push Image to Docker Hub') {         
    steps{                            
 sh 'sudo docker push <dockerhubusername>/<dockerhubreponame>:$BUILD_NUMBER'           
echo 'Push Image Completed'       
    }            
}  

Logout from Docker Hub


This step is mentioned as a post event because we always want to logout from docker hub  irrespective of whether the job ran successfully or not.

post{
    always {  
	sh 'docker logout'     
    }      
}  

You can refer to the complete code in below section. This is the basic code to push a docker image to Docker Hub. You might want to add any security related features to the code to make sure it complies with your company security policy for use in production setup.

Pipeline Code

pipeline {   
  agent{      
    node { label 'slavefordocker'}     
  }  
  environment {     
    DOCKERHUB_CREDENTIALS= credentials('dockerhubcredentials')     
  }    
  stages {         
    stage("Git Checkout"){           
      steps{                
	git credentialsId: 'github', url: 'https://github.com/githubusername/githubreponame'                 
	echo 'Git Checkout Completed'            
      }        
    }
    stage('Build Docker Image') {         
      steps{                
	sh 'sudo docker build -t dockerhubusername/dockerhubreponame:$BUILD_NUMBER .'           
        echo 'Build Image Completed'                
      }           
    }
    stage('Login to Docker Hub') {         
      steps{                            
	sh 'echo $DOCKERHUB_CREDENTIALS_PSW | sudo docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin'                 
	echo 'Login Completed'                
      }           
    }               
    stage('Push Image to Docker Hub') {         
      steps{                            
	sh 'sudo docker push dockerhubusername/dockerhubreponame:$BUILD_NUMBER'                 echo 'Push Image Completed'       
      }           
    }      
  } //stages 
  post{
    always {  
      sh 'docker logout'           
    }      
  }  
} //pipeline

Let us know if you found the post useful.

You may also like...

1 Response

  1. Thanks for that useful tutorial. Gave me some hints I could use. Thanks and go on that way!

Leave a Reply

Your email address will not be published. Required fields are marked *