By clicking “Accept All Cookies”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.
Resources
>
Blog
>
Article
A Jenkins and Docker workflow
December 5, 2017

Building with Docker Using Jenkins Pipelines

This post focuses on building with Docker using Jenkins pipelines.

For starters, if you want to follow along with this exercise, you’ll need:

When installing Docker, make sure to use a Stable release as opposed to an Edge release, or some functionality found in this post may not work.

Preparing the Application and Spinning Up Jenkins

1. First, make sure you are logged in to GitHub in any web browser. Then fork the Spring PetClinic repository (the example application we’ll use). If you want more of a challenge, swap out Spring PetClinic for your own application.

Fork the repository

2. Clone your fork locally. Be sure to replace shanemacbride with your own GitHub username. We will do all work within this directory, so cd into it as well.

$ git clone https://github.com/shanemacbride/spring-petclinic.git 
$ cd spring-petclinic

3. Start up Docker. Our Jenkins container will make use of it.

4. Use Liatrio’s Alpine-Jenkins image, which is specifically configured for using Docker in pipelines. To spin up the Alpine-Jenkins container and give it access to Docker, use docker run. If you are interested in how the image is configured, be sure to look at the liatrio/alpine-jenkins repository’s Dockerfile for an overview.

$ docker run -p 8080:8080 -v 
/var/run/docker.sock:/var/run/docker.sock liatrio/jenkins-alpine

5. Wait for the image to download and run. Afterward, Jenkins should be visible in a web browser at localhost:8080.

Jenkins in a web browser

Creating a Basic Pipeline Job

1. Click a new Pipeline job in Jenkins by clicking New Item, naming it, and selecting Pipeline.

Creating a new pipeline in Jenkins

2. Configure the pipeline to refer to GitHub for source control management by selecting Pipeline script from SCM. Set the repository URL to your fork of Spring PetClinic. The URL I’ve entered here is:  https://github.com/shanemacbride/spring-petclinic.git.

Setting the repository URL on the pipeline

3. Save the job.

Creating a Dockerfile That Runs Our Java Application

1. Create a Dockerfile that will run the Jar generated by Spring PetClinic building. Create a file named Dockerfile using your favorite text editor. We want to start with a Java image, so specify Anapsix’s Alpine Java image as our base image.

FROM anapsix/alpine-java

2. Specify who the maintainer of this image should be using a maintainer label.

LABEL maintainer="shanem@liatrio.com"

3. Ensure the image has the Spring PetClinic on it so it can be run. When Spring PetClinic is built, the Jar will be placed in a target directory. We simply need to copy that into the image.

COPY /target/spring-petclinic-1.5.1.jar /home/spring-petclinic-1.5.1.jar

4. Run Spring PetClinic when the container starts up.

FROM anapsix/alpine-java 
LABEL maintainer="shanem@liatrio.com" 
COPY /target/spring-petclinic-1.5.1.jar /home/spring-petclinic-1.5.1.jar 
CMD ["java","-jar","/home/spring-petclinic-1.5.1.jar"]

5. Commit this new file. We aren’t pushing any changes yet because we still need to create a Jenkinsfile for the Pipeline job to execute correctly.

$ git add Dockerfile 
$ git commit -m 'Created Dockerfile'

Creating a Basic Jenkinsfile

1. Create a Jenkinsfile to instruct our Pipeline job on what needs to be done. First, create the file named Jenkinsfile and specify the first stage. In this stage, we are telling Jenkins to use a Maven image, specifically version 3.5.0, to build Spring PetClinic. After this stage is complete, it will generate a jar and place it in the target directory.

#!groovy
pipeline {
    agent none
   stages {     
    stage('Maven Install') {
      agent {         
       docker {          
         image 'maven:3.5.0'         
     }       
  }       
  steps {
       sh 'mvn clean install'
       }
     }
   }
 }

2. Run our Pipeline job created before. Make sure to push the Jenkinsfile up to GitHub beforehand. You can run the job by clicking on the clock icon to the right. It should successfully install Spring PetClinic using the Maven image.

$ git add Jenkinsfile 
$ git commit -m 'Created Jenkinsfile with Maven Install Stage' 
$ git push
Press the clock icon to run the pipeline job.
Installing the Spring PetClinic using the Maven image.

Adding a Docker Build Stage to the Jenkinsfile

1. Confirm Spring PetClinic is successfully installing. Then package our application inside an image using the Dockerfile created previously. It’s time for another Jenkinsfile stage. In this stage, we won’t require a specific Docker image to be used, so any agent will do. The image will be built using the Dockerfile in the current directory, and it will be tagged with my Docker Hub username and repository as the latest image.

#!groovy

pipeline {
  agent none
  stages {
    stage('Maven Install') {
      agent {
        docker {
          image 'maven:3.5.0'
        }
      }
      steps {
        sh 'mvn clean install'
      }
    }
    stage('Docker Build') {
      agent any
      steps {
        sh 'docker build -t shanem/spring-petclinic:latest .'
      }
    }
  }
}

2. Ensure the image was successfully built (it should be if the updated Jenkinsfile is pushed up to GitHub and the job is run again). You can verify this by either looking at the job’s console output or examining your images through the Docker CLI.

$ git add Jenkinsfile
$ git commit -m 'Added Docker Build Stage'
$ git push
$ # Run the Jenkins job which will execute this new stage and wait for it to finish...
$ docker images
REPOSITORY                TAG   IMAGE ID        CREATED          SIZE 
shanem/spring-petclinic latest ef41393a932d 28 seconds ago 160MB

3. Verify that our Dockerfile was working as expected now that we’ve built our image by running our new image with port 8080, the port that the Java servlet runs on, forwarded to port 8081. We do this because our Alpine-Jenkins container is already running on port 8080. After it spins up, we should be able to see Spring PetClinic in a web browser at localhost:8081. Awesome!

$ docker run -p 8081:8080 shanem/spring-petclinic
Spring PetClinic in a web browser at localhost:8081.

Adding Docker Hub Credentials to Jenkins

Now that we have our application successfully installing and packaging itself into a Docker image, we need to make that image available using Docker Hub.

1. Add your Docker Hub credentials into Jenkins. First, click on Credentials from the Jenkins home page.

Click on Credentials from the Jenkins home page on the left.

2. Click Add credentials under the global drop down menu.

Click Add credentials under the global drop down menu.

3. Enter your Docker Hub credentials. Make sure to use only your Docker Hub username and not your email address. These credentials will be referenced in the Jenkinsfile using their ID value. Hit OK.

Enter your Docker Hub credentials.
Enter your Docker Hub credentials.

Adding a Docker Push Stage to the Jenkinsfile

Finally, the last stage will be added to our Jenkinsfile that pushes our image up to Docker Hub.

1. Create this stage using any agent because we don’t need to run our Docker CLI commands in a specific image. Using withCredentials, we can specify to use our Docker Hub credentials defined within Jenkins to login to Docker Hub via the Docker CLI and push our newly built image up.

#!groovy

pipeline {
  agent none
  stages {
    stage('Maven Install') {
      agent {
        docker {
          image 'maven:3.5.0'
        }
      }
      steps {
        sh 'mvn clean install'
      }
    }
    stage('Docker Build') {
      agent any
      steps {
        sh 'docker build -t shanem/spring-petclinic:latest .'
      }
    }
    stage('Docker Push') {
      agent any
      steps {
        withCredentials([usernamePassword(credentialsId: 'dockerHub', passwordVariable: 'dockerHubPassword', usernameVariable: 'dockerHubUser')]) {
          sh "docker login -u ${env.dockerHubUser} -p ${env.dockerHubPassword}"
          sh 'docker push shanem/spring-petclinic:latest'
        }
      }
    }
  }
}

2. Commit these changes, push them up to the GitHub repository, and trigger our Pipeline job to build in Jenkins.$ git add Jenkinsfile

$ git add Jenkinsfile
$ git commit -m 'Added Docker Push Stage'
$ git push
$ # Run the Jenkins job which will execute this new stage and wait for it to finish...

3. Wait for the job to finish running. Your image should now be on Docker Hub. Great!

Your image should now be on Docker Hub.
Your image now on Docker Hub.

Next Steps

Here, I introduced some of the capabilities that Jenkins brings to the table when working with containerized applications. If you want to take things a step further, be sure to check out Liatrio’s blog on Local Development with Jenkins Pipelines.

If you have any comments or questions, reach out to us.

Ready to get started?

Contact Us

We'd love to learn more about your project and determine how we can help out.