DEV Community

Cover image for How to Automate Docker Build and Push with Jenkins Pipeline.
Joshua Muriki
Joshua Muriki

Posted on • Edited on

How to Automate Docker Build and Push with Jenkins Pipeline.

Jenkins is an automation server that helps automate software development by building, testing, and deploying in continuous integration, and continuous delivery/deployment (CI/CD).

Docker is a software platform used by developers to build, test, and deploy applications into packages called containers containing all the application's dependencies to run on.

Importance of automation in the CI/CD pipeline.

Automation uses machines to accomplish tasks and minimize human intervention—DevOps operations to achieve reliable systems before automation was very hectic. Writing the same codes repeatedly to achieve seamless operations has been time-consuming and costly. Therefore, automation was incorporated into these operations to achieve a more flexible and reliable system with minimal human intervention thus saving on labor and time.

The following are some of the importance of a well-developed CI/CD pipeline;

  • Accelerate software delivery and development cycles
  • Minimal errors as major and complex tasks are automated.
  • Faster review times and resolutions to test code as a large code base is reviewed.
  • Minimize high labor costs for building and testing code.
  • The software released is stable and of high quality.
  • Good time management since the automation process is triggered.

This article explains in detail how to automate docker image creation using Jenkins. Instead of reviewing and building images using docker manually, Jenkins plays a crucial role in automating the process and thus helping the user reduce errors and make time for other important tasks.

Prerequisites

Dockerfile

You will need to have your Dockerfile and its dependencies ready and upload the project to GitHub. To get started on how to create a Dockerfile, refer to this guide Dockerfile.

Before moving forward to automate the Docker Image creation with Jenkins, make sure the Dockerfile can be executed manually to create an image.

Jenkins installations

As explained above, Jenkins is an automation server used to automate building, testing, and deploying software.

In this article, we will install our Jenkins on Windows OS. Visit this link Jenkins to get started on Jenkins installation.

After successfully installing Jenkins, you should be able to access Jenkins via localhost:8080 on your browser as shown in the image below.

Image description

Docker installation

Docker, a platform for containerized applications can comfortably be installed and run on Windows OS. Refer to this guide to get started with Docker.

After successfully installing Docker Desktop, your Docker Desktop app will be similar to the image below.

Image description

Docker Plugin for Jenkins

Docker plugin for Jenkins is a Jenkins plugin developed to support Docker that automates Docker image creation and containerization when Jenkins jobs are triggered. Use this guide Docker-Jenkins plugin to learn more.

Follow the steps below to install the Docker plugin from the Jenkins plugin manager.

  • Access the Jenkins dashboard in a web browser by using the default URL http://localhost:8080 or your configured URL and type in your username and password to log in to your administrator account.

Image description

  • On the Jenkins dashboard, navigate to the left side menu and click Manage Jenkins.

Image description

  • Under System Configuration, clickPlugins.

Image description

  • Then, in the Plugins Section, click Available Plugins (displays all the available plugins). There is a search box for searching all suitable plugins that match your needs.

Image description

  • On the search box, search Docker to output all Docker-related plugins.
  • Look for these plugins; Docker Pipeline Plugin, CloudBees Docker Build and Push plugin, Docker Build Step, and Docker Plugin. Check all their respective checkboxes and click Install.

The plugins will start to download immediately and after successful installation, the respective plugins will show a success message on the right with a green tick.

Image description

  • Restart Jenkins for changes to take effect.
  • After restarting, navigate back to Manage Plugins to check if the Docker plugins are listed in the Installed Plugins tab. Type Docker on the search box to display all installed Docker plugins.

Image description

Setting up Docker for Jenkins

Configuring Docker Host in Jenkins

After successfully installing the Docker plugins and verifying their installation, you will need to configure Jenkins to use Docker as a building tool.

  • On the Jenkins Dashboard, click on Manage Jenkins, and under system configuration, click on Cloud.

Image description

  • Under Cloud, select Add New Cloud.

Image description

  • Choose Docker as your cloud provider and click create.

Image description

  • Jenkins has to communicate with Docker Desktop via a URL.
  • Open Docker Desktop >, Settings >, General.
  • Check the Expose Daemon on tcp://localhost:2375 without TLS. Ignore the warning.
  • Apply and restart Docker.

Image description

  • Go back to Jenkins Docker settings and paste the link tcp://localhost:2375.

Image description

  • Click Test connection to ensure Jenkins can Communicate with Docker.
  • If the connection is successful, it will display the Docker version and API. Click Save.

Image description

Adding Docker Credentials to Jenkins

This step is crucial for pushing the Docker image to Dockerhub. Jenkins will use the docker logins to gain access to the Docker Hub.

On the **Jenkins Dashboard **clickManage Jenkins, under Security, click Credentials.

Image description

Add your Docker Registry credentials that is, set your Docker hub username and password and add a suitable ID then click Create.

Image description

Adding other necessary tools in Jenkins

For the Jenkins pipeline to run smoothly, install tools such as Maven, JDK, and Docker on the Jenkins server.

On the Jenkins Dashboard > Manage Jenkins > system configuration, click Tools.

On JDK installations, add JDK and give it a name, for example, OpenJDK8.

Check the installation automatically. Then choose the installer as install for adoptium.net and select the latest version of JDK.

Image description

Scroll down to Maven installations and add Maven. Check the installation automatically checkbox and choose the installer as install from Apache and select the latest version of Maven.

Image description

Finally, scroll down to Docker installations and select Add Docker.

Choose a suitable name, check the install automatically checkbox, and choose the installer as a download from docker.com. Choose the latest version.

Image description

Configuring Maven POM file.

We will use Maven as a build agent for Jenkins.

On your GitHub repository, create a new file and name it POM.xml.

Paste the below code and save it. (This is a sample Maven Project. Learn more here)

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- Basic project information -->
    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging> <!-- Can also be 'war' for web projects -->

    <name>My Maven Project</name>
    <description>A simple Maven project.</description>
    <url>http://www.example.com</url>

    <!-- Dependencies -->
    <dependencies>
        <!-- Example: Add dependencies here -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>3.1.4</version>
        </dependency>
    </dependencies>

    <!-- Build configuration -->
    <build>
        <plugins>
            <!-- Example: Maven Compiler Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>11</source> <!-- Java source version -->
                    <target>11</target> <!-- Java target version -->
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
Enter fullscreen mode Exit fullscreen mode

The above code is a Maven Project, a build automation tool for Java projects.

Code Breakdown

XML Declaration and Schema

```
Enter fullscreen mode Exit fullscreen mode

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0




This code declares the XML namespace for the POM schema and ensures the file conforms to Maven’s POM structure version 4.0.0.

**Project Data.**



    ```
<!-- Basic project information -->
    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging> <!-- Can also be 'war' for web projects -->

    <name>My Maven Project</name>
    <description>A simple Maven project.</description>
    <url>http://www.example.com</url>
Enter fullscreen mode Exit fullscreen mode

groupId: A unique project group identifier.

artifactId: Unique name of the project within the same group.

version: This has the project version.

packaging: This part shows the type of artifact to produce for example jar for libraries.

name: Name of the Project.

description: Contains description of the project.

url: Project’s website.

Dependencies

```
Enter fullscreen mode Exit fullscreen mode
<dependencies>
    <!-- Example: Add dependencies here -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>3.1.4</version>
    </dependency>
</dependencies>
Enter fullscreen mode Exit fullscreen mode



This part declares the libraries required for the project. It specifies Spring Boot Starter dependency version 3.1.4.

**Build Configuration**



    ```
<!-- Build configuration -->
    <build>
        <plugins>
            <!-- Example: Maven Compiler Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>11</source> <!-- Java source version -->
                    <target>11</target> <!-- Java target version -->
                </configuration>
            </plugin>
        </plugins>
    </build>
Enter fullscreen mode Exit fullscreen mode

This code snippet configures the project build process. The plugin adds build plugins to extend Maven’s functionality targeting Java 11.

Creating a Jenkins pipeline

Jenkins pipelines are a set of plugins that contain automated steps that Jenkins executes to build, test, and deploy applications. It is from these pipelines that continuous delivery and integration are implemented to achieve highly flexible and robust applications.

Writing a Jenkins file

Below is a sample of a Jenkins pipeline designed to automate the process of checking the code, building a Docker image, and pushing the created image to a Docker hub.

Sample Jenkins Code.

pipeline {
    agent any 

    stages {
        stage ('Checkout Code') {
            steps {
                checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/joshwizard/Docker-Image-Build-Automation-with-Jenkins.git']])
            bat 'mvn clean install'
            }
        }

        stage('Build Docker Image') {
            steps {
                script{
                    bat 'docker build -t joshmurih/flaskapp:latest .'
                }
            }
        }

        stage('Push Image to Hub') {
            steps {
                script {
                    withCredentials([usernamePassword(credentialsId: 'dockerhubpassword', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
                        bat """
                        echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
                        docker push joshmurih/flaskapp:latest
                        """
            }
        }
    }
}

    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation of each stage in the pipeline.

Pipeline Overview

pipeline {
    agent any
    ...
}
Enter fullscreen mode Exit fullscreen mode

Pipeline: This is what defines the entire Jenkins pipeline.

Agent any: Communicates with Jenkins to run the pipeline on any available agents. You can specify the containers if need be.

Stages and Steps

The stages in the pipeline show phases that the Jenkins pipeline follows to accomplish specific tasks.

Stage 1: Checkout Code

stage ('Checkout Code') {
            steps {
                checkout scmGit(branches: [[name: '*/main']], extensions: [], userRemoteConfigs: [[url: 'https://github.com/joshwizard/Docker-Image-Build-Automation-with-Jenkins.git']])
            bat 'mvn clean install'
            }
        }
Enter fullscreen mode Exit fullscreen mode

Checkout Code: This part retrieves the latest code from a Git Repository and builds it using Maven.

steps: Contains the tasks to be executed in this stage.

  • Checkout scmGit: Checks out the code from the specified Git repository branch (Main).
    • branches: Specifies the branch to fetch the code.
    • userRemoteConfigs: Contains the GitHub repository URL.
  • bat 'mvn clean install' : Runs Maven command to clean and build the project. bat is a command for Windows, sh is built for Unix/Linux platforms.

Stage 2: Build Docker Image

stage('Build Docker Image') {
            steps {
                script{
                    bat 'docker build -t joshmurih/flaskapp:latest .'
                }
            }
        }
Enter fullscreen mode Exit fullscreen mode

Build Docker Image: This stage will build a Docker image using the project’s Dockerfile.

script: specifies code to run for execution.

bat 'docker build -t joshmurih/flaskapp:latest .': This command executes a Docker build image command.

Stage 3: Push Docker Image

stage('Push Image to Hub') {
            steps {
                script {
                    withCredentials([usernamePassword(credentialsId: 'dockerhubpassword', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {
                        bat """
                        echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin
                        docker push joshmurih/flaskapp:latest
                        """
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

Push Docker Image: After building the Docker image, this stage pushes the Docker image to the Docker Hub.

withCredentials: Securely injects credentials from the Jenkins credentials system server.

credentialsId: This contains Docker Hub credentials (username and password).

usernameVariable: This step binds the Docker Hub username to DOCKER_USER.

passwordVariable: This step binds the Docker Hub password to DOCKER_PASS.

The code runs under bat command, logs into the Docker Hub.

docker push joshmurih/flaskapp:latest: This command pushes the Docker image to Docker Hub successfully.

Running the pipeline Job

Creating the pipeline job in Jenkins

Now after everything is set, a job must be created to enable the build and push to take place effectively.

When a job is created, you can schedule build and push by setting a trigger of your choice or do it manually.

To create a Jenkins pipeline;

Sign in to your Jenkins dashboard and click the new item.

Image description

A new page is displayed and asks for an item name. Enter a suitable name for your Jenkins pipeline.

On the Select Item Type, choose Pipeline and click OK.

Image description

A new configuration page is displayed where all the settings of the pipeline take place.

Type a short and brief description of your project in the text area provided.

Image description

Check the Discard old builds to prevent accumulating old builds that have no use in your dashboard.

Put a maximum of 2 builds (It depends on your preference.)

Image description

Under Build Triggers

Check the checkbox for the GitHub hook trigger for GITScm polling.

Image description

Note: To understand better the build triggers, at the end of every command there is a question mark that contains more detailed information of what that particular command does.

On the Pipeline part, select pipeline script.

Copy and paste the sample Pipeline Jenkins code on the script area click apply to capture changes and save to close the window.

Image description

A page is displayed and on the left side of the page, click Build Now to start building your project.

Image description

When building the project, open your pipeline project, click on the project building number starting with #, and click Console Output to monitor the project's progress. (It also contains error logs if the project fails to execute properly).

Image description

If the process is successful, open Docker Desktop and confirm the docker image. Thereafter, open Docker Hub on your browser and check if your image has been published.

Best practices

Security Considerations

Publishing Docker images to Docker Hub can be vulnerable especially if Docker credentials are not securely configured.

Use Jenkins credentials to manage sensitive information like APIs, usernames and passwords, and Docker Hub credentials.

pipeline {
    environment {
        DOCKER_CREDS = credentials('docker-registry-credentials-id')
    }
    stages {
        stage('Login to Docker Registry') {
            steps {
                sh 'echo $DOCKER_CREDS_PSW | docker login -u $DOCKER_CREDS_USR --password-stdin'
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Pipeline Simplicity

Use clean and structured code syntax which is easier to debug in case an error occurs.

Make sure to maintain clean indentation and flow of code syntax which can also be used in future projects by simply changing some commands, steps, or stages.

Docker Image Management

Ensure a proper workspace cleanup to free up space to avoid disk space-related issues.

Cleaning the Docker workspace creates an efficient platform to run other newly created images without taking into consideration space issues.

Use the code below in your pipeline script to clean up space after the image has been built.

stage('Clean Up') {
    steps {
        sh 'docker system prune -f'
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

This article has covered all the relevant steps to build and push the created Docker image to Docker Hub using well defined Jenkins Pipeline from checkout code, building the image, and pushing to Docker Hub.

The pace of technological innovation is accelerating and as a result, always counter-check for new updates on plugins to avoid unnecessary errors.

Also, save the pipeline script as Jenkinsfile in your GitHub Repository to use later by running the Pipeline Script from SCM on the Jenkins pipeline instead of writing a new script.

Explore other automation possibilities with Jenkins and Docker to make work easier and pave the way for other project priorities.

Top comments (0)