Continuous Integration and Continuous Delivery by Dockerize Jenkins Pipeline

Introduction

Continuous Integration and Continuous Delivery highly fundamental topics in the software industry especially with the cloud and container technologies.

Container technologies such as DockerKubernetesOpenShift and automation servers like Jenkins make easier to manage our projects workflow.

In this session we will pull sample Jenkins pipeline code from the GitHub repository and create jerkins pipeline using docker containers.

The processes we want to automate for this project:

  • Code checkout
  • Run tests
  • Compile the code
  • Run Sonarqube analysis on the code
  • Create Docker image
  • Push the image to Docker Hub
  • Pull and run the image

Before We Begin

  • Ubuntu 18.04 server with root or non-root user with sudo privileges
  • Docker Installed
  • Docker compose Installed

To know how to install Docker and Docker compose check out our previous tutorials sessions on Install Docker and Install docker-compose

Running up the services using docker-compose

Since one of the goals is to obtain the sonarqube report of our project, we should be able to access sonarqube from the Jenkins service. Docker-compose is the best choice to run services working together.

To learn more about sonarqube visit sonarqube official documentation

Create a folder named jenkins-pipeline-demo. We will configure our application services in docker-compose.yml in this folder as below :

Paths of docker files of the containers are specified at the context attribute in the docker-compose file. Content of these files as follows:

nano docker-compose.yml


version: '3.2' 
services:
  sonarqube:
    build:
      context: sonarqube/
    ports:
      - 9000:9000
      - 9092:9092
    container_name: sonarqube
  jenkins:
    build:
      context: jenkins/
    privileged: true
    user: root
    ports:
      - 8080:8080
      - 50000:50000
    container_name: jenkins
    volumes:
      - /home/jenkins:/var/jenkins_home 
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - sonarqube

We are using two Dockerfiles as below :

FROM sonarqube:lts #sonarqube/Dockerfile

FROM jenkinsci/blueocean #jenkins/Dockerfile

So now our Directory structure look like :

Note:We have two Dockerfiles (inside jenkins & sonarqube folder)

If we run the following command in the same directory as the docker-compose.yml file, the Sonarqube and Jenkins containers will up and run.

sudo docker-compose -f docker-compose.yml up --build

You will get output look like :

Next check our created containers are running properly or not :

docker ps

We can see that both Jenkins and sonarqube containers are running on specified ports

Jenkins configuration

For this tutorial I am using local ubuntu machine and our jenkins container can be accessed as localhost:8084

To know how to Unlock Jenkins, Create admin user and Install suggested plugins visit our previous tutorials on How to install and configure Jenkins using Docker containers

Install Maven and Docker client on Jenkins

One of our main objective is , we must have the ability to build an image in the Jenkins being dockerized. Take a look at the volume definitions of the Jenkins service in the compose file.

- /var/run/docker.sock:/var/run/docker.sock

The purpose is to communicate between the Docker Daemon and the Docker Client(we will install it on Jenkins) over the socket. Like the docker client, we also need Maven to compile the application. For the installation of these tools, we need to perform the Maven and Docker Client configurations under Manage Jenkins -> Global Tool Configuration menu.

Note: If you use Jenkins docker images other than blueocean like jenkins/jenkins:lts , sometimes Docker option unavailable on tool configuration. At that time you need to Install Docker plugin manually. So recommended way is to use jenkinsci/blueocean image

Install Dockerclient

Give name to our Dockerclient tool as myDocker and check the Install automatically checkbox.

From the Add installer dropdown,select Download from docker.com.

Your Docker version will show as latest automatically as shown in below :

Install maven also by giving name as myMaven and selecting install automatically option with latest version

Save these settings by clicking apply& save .

These tools are installed by Jenkins when our script(Jenkins file) first runs.We will access these tools with this names in the script file.

Configure Docker hub and Git for Jenkins

In order to perform code checkout and pushing an image to Docker Hub we need to define their credentials on jenkins.These definitions are performed under Jenkins Home Page -> Credentials -> Global credentials (unrestricted) -> Add Credentials menu.

Give your Dockerhub account username ,password and specify ID as myDockerhubaccount.We need to specify this ID to Docker login in the script file.

Note: We will configure GitHub credentials during the Jenkins Job configuration steps. You can clone the jenkins-pipeline project from my repo https://github.com/rjshk013/jenkins-pipelinetest in your own Github account and configure in upcoming steps

Now, we will define pipeline under Jenkins Home Page -> New Item menu.

Give an item name as Jenkins-pipeline_demo -> select Pipeline project ->OK

In General section,Select Github project and give your Github repository for the project

Go to Pipeline section ->  select the Pipeline script from SCM as Definition, define the GitHub repository and the branch name, and specify the script location (Jenkins file).

Note:Configure your GitHub repository credentials in this step

Save the configuration by apply & save.

After that, when a push is done to the remote repository or when you manually trigger the pipeline by Build Now option, the steps described in Jenkins file will be executed.

After successful build you can see the pipeline stage as :

Check docker image pushed into DockerHub

As jenkinsfile Docker image of our application will be pushed into DockerHub.I can see the newly created dockerimage named jenkins-pipelinedemo in my repositories

Check docker application is running on local machine:

Now check our newly created jenkins-pipeline demo application is running or not

docker ps

As you can see application is running on port 8090.Now check the application on the browser .You will get output look like :

Review important points of the Jenkins file

stage('Initialize'){
    def dockerHome = tool 'myDocker'
    def mavenHome  = tool 'myMaven'
    env.PATH = "${dockerHome}/bin:${mavenHome}/bin:${env.PATH}"
}

The Maven and Docker client tools we have defined in Jenkins under Global Tool Configuration menu are added to the PATH environment variable for using these tools with sh command.

stage('Push to Docker Registry'){
    withCredentials([usernamePassword(credentialsId: 'dockerHubAccount', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
        pushToImage(CONTAINER_NAME, CONTAINER_TAG, USERNAME, PASSWORD)
    }
}

withCredentials provided by Jenkins Credentials Binding Plugin and bind credentials to variables. We passed dockerHubAccount value with credentialsId parameter. Remember that, dockerHubAccount value is Docker Hub credentials ID we have defined it under Jenkins Home Page -> Credentials -> Global credentials (unrestricted) -> Add Credentials menu. In this way, we access to the username and password information of the account for login.

Sonarqube configuration

For Sonarqube we have made the following definitions in the pom.xml file of the project.

<sonar.host.url>http://sonarqube:9000</sonar.host.url>
...
<dependencies>
...
    <dependency>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sonar-maven-plugin</artifactId>
        <version>2.7.1</version>
        <type>maven-plugin</type>
    </dependency>
...
</dependencies>

In the docker compose file, we gave the name of the Sonarqube service which is sonarqube, this is why in the pom.xml file, the sonar URL was defined as http://sonarqube:9000.

Conclusion

In this tutorial we learned how to dockerize a sample Jenkins pipeline application with docker compose and code from GitHub repository.

Leave a Reply