Using Docker to run Jenkins jobs

Here is a small recipe you can use to run Jenkins jobs in Docker containers.
Docker is a solution to easily automate the deployment and execution of applications inside software containers on top of Linux. The main advantages to use containers are the isolation of resources, restriction of services, and processes provisioned to have a private view of the operating system. To summarize, containers helps to isolate a process and its dependencies. With container, it is also very easy (and cheaper than virtual machines) to start from the same initial container state for each run. It is a very good property for Continuous Integration to have reproducible builds without side effects.
Instruction given below are valid for the latest Ubuntu LTS distribution but can be easily adapted to other distributions.

Install Docker

Official documentation on how to install Docker on Ubuntu can be found here.
You could simply use:
curl -sSL https://get.docker.io/ubuntu/ | sudo sh
but the latest version of docker is not yet supported by the Jenkins Docker plugin. In the same time, the default docker package for Ubuntu LTS is very old and has some bugs. That’s why it is preferable to use the version 1.1.2 of Docker. Then you will have to execute the following instruction to get Docker 1.1.2 installed:

# Check that HTTPS transport is available to APT
if [ ! -e /usr/lib/apt/methods/https ]; then
	apt-get update
	apt-get install -y apt-transport-https
fi

# Add the repository to your APT sources
echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list

# Then import the repository key
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9

# Install docker
apt-get update
apt-get install -y lxc-docker-1.1.2

To check that the installation succeeded, run

sudo docker run -i -t ubuntu /bin/bash

By default, Docker listens to a Unix socket and not a TCP port. To change this default behaviour (needed to work with Java and the Docker Jenkins plugin), edit the Docker configuration file (/etc/default/docker) to add:
DOCKER_OPTS="-H=tcp://127.0.0.1:4243".
Don’t forget to restart docker to get the previous update applied: sudo docker restart

Note:
With the previous change, you will need to give the -H=tcp://127.0.0.1:4243 option to the docker command.
Ex: sudo docker -H=tcp://127.0.0.1:4243 run -i -t jenkins-slave /bin/bash.
To avoid that, it is possible to define the DOCKER_HOST environment variable:
export DOCKER_HOST=tcp://127.0.0.1:4243

Create a Docker image to be used by Jenkins slaves

A Docker image is a template that is used to create new containers. It includes everything needed to run the process you want (here a Jenkins job) inside the container.
The way do that is to create a Dockerfile with all instructions needed to build an image.

cat > Dockerfile
# This Dockerfile is used to build an image containing basic stuff to be used as a Jenkins slave build node.

FROM ubuntu:latest
MAINTAINER Christophe Demarey

# Make sure the package repository is up to date.
# RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update

# Install a basic SSH server
RUN apt-get install -y openssh-server
RUN mkdir -p /var/run/sshd

# Install JDK 7 (latest edition)
RUN apt-get install -y --no-install-recommends openjdk-7-jdk

# Install packages needed for the build
RUN apt-get install -y --no-install-recommends git maven

# Add user jenkins to the image
RUN adduser --quiet jenkins
# Set password for the jenkins user (you may want to alter this).
RUN echo "jenkins:jenkins" | chpasswd

# Standard SSH port
EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]

The given script will produce a new Docker image from a basic Ubuntu image, by adding SSH, JDK, git and maven, as well as a new user jenkins with password jenkins. It also set the default command to execute: sshd.
If the build needs more system dependencies, they should be added in this file.

To generate the Docker image, run sudo docker build -t jenkins-slave . in the directory containing the Dockerfile.

Configure Jenkins

Configure global security

Disable builds on the master: Manage Jenkins / Manage Nodes / Master / Configure and set the number of executors to 0.

Docker Plugin

Install the Docker plugin from the plugin manager (Manage Jenkins / Manage plugins).
The, configure the Docker plugin (Manage Jenkins / Configure System / Docker) with following information:

  • name: local docker
  • url: http://localhost:4243
  • image
    • id: jenkins-slave
    • credentials: jenkins/jenkins
    • remote fs: /home/jenkins
    • instance cap: 0 (unlimited)

We gave information to Jenkins so that he knows:

  • how to contact the docker instance,
  • which Docker images are usable from Jenkins (we just declared one image).

Configure your job to use Docker

The last part you need to run jobs on Docker containers is to configure the job.
Here, some magic happens: you just need to tell your job to use a Docker image and Jenkins will magically create a new Docker container on-demand (i.e. when the job is triggered) from the specified Docker image.
To specify the Docker image to use, put the image id in the Restrict where this project can be run field of the job configuration.

Leave a Reply