Introduction

Hi everyone. In this tutorial we will create a docker image with jenkins and send then to dockerhub.

What’s docker? Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications.

You can learn more about docker in docker website

Why pipeline? You can reuse everything you did, put your jenkins code inside git project, the change in pipeline is showed in “changes” inside job history

What’s dockerhub? Dockerhub is a public docker registry to store your docker images inside. If you want a private registry, you can pay for it. We will use it because it is the most easeful docker registry.

What’s docker registy? Docker registry is a server to distribute versions of docker images.

Jenkins with docker installed

We will use some pipeline codes, the jenkins need have installed docker inside him to find this commands.

I created a docker image of jenkins with docker installed.

Let’s see the Dockerfile:

FROM jenkins/jenkins:lts

USER root

RUN apt-get update && \
apt-get -y install apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common && \
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && \
add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
   $(lsb_release -cs) \
   stable" && \
apt-get update && \
apt-get -y install docker-ce

RUN apt-get install -y docker-ce

RUN usermod -a -G docker jenkins

USER jenkins

This Dockerfile is builded from jenkins official image, install docker and give access to user jenkins build dockers.

You can build this image, but is already in dockerhub gustavoapolinario/jenkins-docker.

Running jenkins with docker from host

To run the container, you need add a volume in docker run command.

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

It will share the docker socket (used in your machine) with the container.

The complete run command:

docker run --name jenkins-docker -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock gustavoapolinario/jenkins-docker

After inicialized the jenkins, complete the jenkins startup wizard.

Read this tutorial to complete wizard and install the locale and blueocean plugins: Quick start with jenkins in docker.

Creating a job to test docker command

In home of jenkins, click on “New Item”, select “Pipeline” and put the job name as “docker-test”.

New pipeline Job

Put this script inside of job:

pipeline {
    environment {
        registry = "docker_hub_account/repository_name"
        registryCredential = 'dockerhub'
    }
   
    agent any
    
    stages {
        
        stage('Building image') {
            steps{
                script {
                    docker.build registry + ":$BUILD_NUMBER"
                }
            }
        }
    }
}

The screen will be like this:

Pipeline in job config

Save the job.

Pipeline explanation

In this pipeline, We have 2 environment variables to change the registry and the credential easeful.

environment {
    registry = "docker_hub_account/repository_name"
    registryCredential = 'dockerhub'
}

The job will have one step. It will run the docker build and use the jenkins build number in docker tag. With build number turn easeful to deploy or rollback based in jenkins.

stages {
    stage('Building image') {
        steps{
            script {
                docker.build registry + ":$BUILD_NUMBER"
            }
        }
    }
}

Testing the docker command in job

Click on “Build Now” in job’s menu.

Job Menu

The job will failure. Don’t worry.

Build Failure

In job’s home, you can click in circle and see the console output.

Build History

Or click on build number (#1) and click on “Console Output”.

Job Build Menu

In Console Output you will see this:

Started by user GUSTAVO WILLY APOLINARIO DOMINGUES
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/docker-test
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Building image)
[Pipeline] script
[Pipeline] {
[Pipeline] sh
[teste234] Running shell script
+ docker build -t docker_hub_account/repository_name:1 .
unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /var/jenkins_home/workspace/docker-test/Dockerfile: no such file or directory
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 1
Finished: FAILURE

The error happens because the Dockerfile is not finded. We will resolve it soon.

The docker command is executed and the jenkins found the command.

Creating a dockerhub repository

Create a dockerhub account, if you don’t have yet.

dockerhub

Logged in dockerhub, click on “Create” > “Create Repository”.

Dockerhub menu to Create Repository

Put a name for your repository. For this example, use “docker-test”.

Creating Dockerhub Repository

After docker repository created, get the name to use in our pipeline. In my case, the name is “gustavoapolinario/docker-test”.

Dockerhub Repository

Creating dockerhub credential

Go to jenkins home, click on “credentials” and “(global)”.

Credentials

Click on “Add Credentials” in left menu.

Global Credentials

Put your credential and save it.

Creating Dockerhub Credentials

Remenber to change the credential environment (registryCredential) if you didn’t put “dockerhub” in Credential ID.

The credential is configured.

Configuring the environment of dockerhub

Alter the job pipeline. Go to jenkins home, click on job name (docker-test), click on “Configure” in job menu.

The code you need to change is:

environment {
    registry = "docker_hub_account/repository_name"
    registryCredential = 'dockerhub'
}

Change the environment variable “registry” to your repository name. In my case is “gustavoapolinario/docker-test”.

Change the environment variable “registryCredential” if necessary.

My environment is:

environment {
    registry = "gustavoapolinario/docker-test"
    registryCredential = 'dockerhub'
}

Building the first docker image

With dockerhub credential and repository created, the jenkins can send the docker image builded to dockerhub (our docker repository).

In this example, let’s build a node.js application. We need a Dockerfile to the build.

Let’s create a new step in pipeline to clone a git repository that have a Dockerfile inside.

stage('Cloning Git') {
    steps {
        git 'https://github.com/gustavoapolinario/microservices-node-example-todo-frontend.git'
    }
}

The pipeline must be (but using your environment):

pipeline {
    environment {
        registry = "gustavoapolinario/docker-test"
        registryCredential = 'dockerhub'
    }
   
    agent any
    
    stages {
        stage('Cloning Git') {
            steps {
                git 'https://github.com/gustavoapolinario/microservices-node-example-todo-frontend.git'
            }
        }
        
        stage('Building image') {
            steps{
                script {
                    docker.build registry + ":$BUILD_NUMBER"
                }
            }
        }
    }
}

Save and run it clicking on “Build Now”

The Stage view in jenkins job will change to this:

Stage View with git

Deploying the docker image to dockerhub

At this moment, we clone a git and build a docker image.

We need put this image in docker registry to pull it in other machines.

First, create a environment to save docker image informations.

dockerImage = ''

Change the build stage to save build information in environment.

dockerImage = docker.build registry + ":$BUILD_NUMBER"

Ceate a new stage to push the docker image builded to dockerhub

stage('Deploy Image') {
    steps{
        script {
            docker.withRegistry( '', registryCredential ) {
                dockerImage.push()
            }
        }
    }
}

The final code will be (remember, using your environment):

pipeline {
    environment {
        registry = "gustavoapolinario/docker-test"
        registryCredential = 'dockerhub'
        dockerImage = ''
    }
   
    agent any
    
    stages {
        
        stage('Cloning Git') {
            steps {
                git 'https://github.com/gustavoapolinario/microservices-node-example-todo-frontend.git'

            }
        }
        
        stage('Building image') {
            steps{
                script {
                    dockerImage = docker.build registry + ":$BUILD_NUMBER"
                }
            }
        }
        stage('Deploy Image') {
            steps{
                script {
                    docker.withRegistry( '', registryCredential ) {
                        dockerImage.push()
                    }
                }
            }
        }
    }
}

Save and run it.

Awesome, the build is complete and the image will be send to docker registry.

Complete pipeline to a node.js application

This step is for who did this tutorial: Jenkins Starting with Pipeline doing a Node.js test.

To complete the node.js pipeline, let’s change this pipeline to merging with node.js build and test.

The complete pipeline will be:

pipeline {
    environment {
        registry = "gustavoapolinario/docker-test"
        registryCredential = 'dockerhub'
        dockerImage = ''
    }
   
    agent any
    
    tools {nodejs "node" }
    
    stages {
        
        stage('Cloning Git') {
            steps {
                git 'https://github.com/gustavoapolinario/microservices-node-example-todo-frontend.git'

            }
        }
        
        stage('Build') {
            steps {
                sh 'npm install'
                sh 'npm run bowerInstall'
            }
        }
        
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
        
        stage('Building image') {
            steps{
                script {
                    dockerImage = docker.build registry + ":$BUILD_NUMBER"
                }
            }
        }

        stage('Deploy Image') {
            steps{
                script {
                    docker.withRegistry( '', registryCredential ) {
                        dockerImage.push()
                    }
                }
            }
        }
    }
}

Now you have a pipeline for test and create a docker image for your application.

Thanks.