Run Jenkins Automation Server as Docker Image

Introduction

Even for my side projects it is convenient to have my personal automation server run. As far as I know, this type of server is also known as Continues Integration CI environment and I use those terms interchangeable. Beside being convenient, it is also fun and I might even learn something from it!

The most popular open source CI at this moment is Jenkins. So that is the one I am going to install.

To simplify the installation of Jenkins I chose to use Docker. Why Docker? Because it can, it is popular and to learn something from it.

You might already know but just for the completeness. What is Jenkins and What is Docker?

About Jenkins

Jenkins is an open source automation server written in Java. Jenkins helps to automate the non-human part of the software development process, with continuous integration and facilitating technical aspects of continuous delivery. It is a server-based system that runs in servlet containers such as Apache Tomcat. 

Wikipedia

About Docker

Docker is used to run software packages called “containers”. Containers are isolated from each other and bundle their own application, tools, libraries and configuration files; they can communicate with each other through well-defined channels. All containers are run by a single operating system kernel and are thus more lightweight than virtual machines.

Wikipedia

Why Run Jenkins as Container?

Well, an advantage of running Jenkins as a container is that there is no need to install Java and other requirements to run Jenkins. It is easy to get the latest version of Jenkins, it is just a matter of starting docker. During start, Docker will test if it has the the latest version of the image available and will download the latest version if needed. Docker is already a requirement of Jenkins for running the pipeline in an isolated environment anyway, so that means no extra requirements beside Docker.

The Build Process

Getting up and running with Jenkins was indeed just a matter of starting the Jenkins image, so that was easy! I created my first multi pipeline project and started the build. The pipeline starts a new Docker environment and tries to start maven in it, but the first attempt running the Maven build process was not successful.

Unfortunately by default maven appears not to be installed within the Jenkins container. It needs to be added to the image. Beside maven, imagemagick is used in my JUnit tests, so let’s add that one also.

We are almost there, but starting a Docker container from Jenkins running from a Docker container is not possible by default. Jenkins will fail with the following error:

docker not found

The trick here is to install Docker on the Jenkins container itself and mount the docker socket into the Jenkins Docker container when starting Jenkins. Thanks to Tharaka Devinda for a solution to this.

Create Customized Jenkins Docker Image

To create a customized Jenkins Docker image with maven, imagemagick and the docker client added, create a Dockerfile with the following contents:

FROM jenkins/jenkins:lts
USER root
RUN apt-get update && apt-get install -y maven imagemagick
RUN curl -sSL https://get.docker.com/ | sh

Start Customized Jenkins Docker Image

To make the configuration of the Jenkins server a little easier, I use docker-compose. Create a docker-compose.yml file with the following contents:

    jenkins:
    container_name: custom_jenkins
    build: ./
    ports:
            - "127.0.0.1:8080:8080"
            - "127.0.0.1:50000:50000"
    volumes:
            - /opt/jenkins_home:/var/jenkins_home
            - /var/run/docker.sock:/var/run/docker.sock
    environment:
            JENKINS_OPTS: "--prefix=/jenkins"
    restart: always

To start the server, just start “docker-compose”. Open the following URL in the browser: http://localhost:8080/jenkins 

Run Jenkins Behind Proxy

My development server contains multiple tools like Bitbucket and others. All of them run on different context paths and are secured with SSL. I use Apache to offload the SSL and to serve the pages.

The Apache reverse proxy configuration for this looks like:

ProxyPreserveHost On
ProxyPass /jenkins http://127.0.0.1:8080/jenkins nocanon
ProxyPassReverse /jenkins http://127.0.0.1:8080/jenkins
ProxyRequests Off
AllowEncodedSlashes NoDecode
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"

Since then my Jenkins build server is running fine.

Resources

Jenkins, the leading open source automation server:
https://jenkins.io

Stackoverflow: extend jenkins image to install maven:
https://stackoverflow.com/questions/46052711/extend-jenkins-image-to-install-maven

Blog: Running Jenkins on Docker — for a newbie:
https://medium.com/gdgsrilanka/running-jenkins-on-docker-for-a-newbie-855ad376500b

A fully functional Jenkins server, based on the weekly and LTS release within a Docker container:
https://github.com/jenkinsci/docker/blob/master/README.md

Running Jenkins behind Apache
https://wiki.jenkins.io/display/JENKINS/Running+Jenkins+behind+Apache