Fork me on GitHub

Programming, Internet & more

Continuous Delivery with Jenkins and Docker

If you’ve ever wondered how to actually build a continuous delivery pipeline for your project this is going to be the ultimative guide. I will tell you how you can build a continuous delivery pipeline from ground up.

The pipeline will make heavy use of Jenkins together with Docker to provide a stable platform to build on.

The overall goal is to setup a build process which runs on every commit, compiles all the classes, runs all the unit tests and automatically deploys the application to provide a running instance which could be used by testers.

Requirements

To follow this guide you will need a few applications installed. I will use Vagrant to create a virtual machine (vagrant box) which will make it really easy for you to follow and avoid installing a bunch of software on your machine.

Applications on your machine (host):

Applications on vagrant box (guest):

Setting up vagrant

The first thing you have to do is install VirtualBox and Vagrant. It’s pretty easy just follow the instructions of the installers.

If you have done that you can clone the repository from github that I’ve prepared. In the repository there is a Vagrantfile which will setup your virtual machine with all the necessary stuff.

After you’ve cloned the repository open a command shell in the cloned directory and start the virtual machine.

vagrant up

Depending on your internet connection it may take a while until that command has finished. This command will do a lot of work by downloading and installing all the applications on the virtual machine that we’ll need in a minute.

Once the command has finished you can log into the vagrant box.

vagrant ssh

This command will ssh into the virtual machine and should look like this:

Vagrant ssh

Preparing jenkins

When you startup your vagrant box jenkins will be automatically started in the background.
As soon as jenkins is up and running you can open a browser on your host machine and navigate to jenkins http://localhost:9080.

Now lets install some plugins for jenkins:

  • Git plugin to be able to fetch git projects from github
  • Copy Artifact plugin to be able to copy artifacts from one project to another

The easiest way is by navigating to Manage Jenkins -> Manage Plugins -> Available and filter for the plugin names

Jenkins install plugins

As soon as the plugins are installed you have to install maven to be able to build maven projects. This can be done in Manage Jenkins -> Configure System -> Maven .

Jenkins install maven

Configuring the build job in jenkins

You can now create your first build job which will compile your application and run some basic unit tests. We’ll be using slackspace-javaee-classpath-properties as an example application. The project is a Java EE application hosted on GitHub so it’s pretty easy to include the project into our pipeline. As the project uses maven we can easily compile it without having to worry about dependencies.

Create a new maven project in your jenkins with name “javaee-classpath-properties-build”.
Now you have to choose Git as Source Code Management system and use the correct url to the repository: https://github.com/cternes/slackspace-javaee-classpath-properties.git.

Jenkins maven project
Jenkins configure source code management

As build goal use package as we want to compile the project and package all the classes into a *.war file.

Jenkins configure maven goals in project

The last step is to define a post-build action called Archive the artifacts. The files to archive should be set to target/*.war. This will ensure that it is possible to access the packaged war-file in another project later on.

You can now test if the job works by clicking on the Build Now button. If everything works the job should be displayed with a blue circle after a while.

Configuring the staging job in jenkins

Now it is time to configure another job that will make use of docker containers to provide a running instance of the application for testing.

First of all create another jenkins job named javaee-classpath-properties-staging. The type should be Freestyle project.

Jenkins free-style project

Leave the Source Code Management untouched. Instead check the build trigger Build after other projects are built and enter the name of our build project (javaee-classpath-properties-build).

Add a build step of type Copy artifacts from another project and enter the following properties:

  • Project name: javaee-classpath-properties-build
  • Which build: Latest successful build
  • Check Stable build only
  • Artifacts to copy: target/*.war

Add another build step Execute shell and insert the command:

docker ps -a | grep 'javaee-classpath-properties-staging:latest' | awk '{print $1}' | xargs --no-run-if-empty docker kill

echo "FROM glassfish:4.1\nMAINTAINER cternes <github@slackspace.de>\n# Deploy application\nADD target/javaee-classpath-properties.war /usr/local/glassfish4/glassfish/domains/domain1/autodeploy/" > $WORKSPACE/Dockerfile

service=$JOB_NAME
service_port=8080
docker build -t $service $WORKSPACE
container_id=$(docker run -d -p $service_port:$service_port $service)

echo "App running on http://localhost:$service_port/javaee-classpath-properties/"

Jenkins Docker Build Step

Ok, let me explain what we’ve just did. We have configured another job which will be started automatically after our build job. The job will only be triggered if the build job was successful. We’ve also configured that the generated war-file from our build job will be copied to the staging job and therefore will be reused. This ensures that we’re using exactly the same file that was compiled and tested during the build job. This is an extremely important concept because we’re now indepent from other commits which have been done during the time the build job was running and eventually are breaking the build.

The main work which is done in this job is a little bit cryptic, hidden in the Execute shell build step. What it basically does is creating a Dockerfile and then building a new docker image with that Dockerfile.

While building the docker image it is downloading a glassfish docker container and injects our generated war-file into it. After that the docker container will be started, which means the Glassfish Java EE Application Server will be started and our application will be automatically deployed into the Glassfish. As soon as the docker container is running we can access our application through the browser by opening http://localhost:8080/javaee-classpath-properties/.

You can now test if everything works by “building” the staging job.

Putting it all together

The hard work is done. You can see the results by building the job “javaee-classpath-properties-build” in your jenkins. This will compile the application, run the tests and package the application. When the first job has finished successfully, the second job will be triggered automatically and will fire up a docker container with your application inside.

After a short time you should have access to your application and can test it in the browser. Note how fast the docker container starts up. On my machine the second job runs at most times under a second. That’s amazingly fast to startup a whole testing environment from the ground.

Next Steps

You’ve learned the basics how to build a continuous delivery pipeline with Jenkins and Docker. There is a lot more what can be done from here like configuration management, acceptance tests, service discovery, monitoring and so on.

But this article should be only a kickstart to develop your own ideas. Any comments or feedback is appreciated.

Category: javaee, programming, tutorials
-->

One Comment

  1. Bavo Bruylandt
    Posted October 30, 2015 at 13:41 | Permalink

    Works as documented, impressive! Thanks

Post a Comment

Your email is kept private. Required fields are marked *

*
*