Skip to content
vanpeerdevelopment edited this page Jan 15, 2016 · 5 revisions

Dockerfile

# Dockerfile
FROM jenkins:1.625.3

ENV JENKINS_OPTS --httpPort=8888

USER root
RUN apt-get update && apt-get install -y lxc

COPY config.groovy /usr/share/jenkins/ref/init.groovy.d/config.groovy

COPY plugins.txt /usr/share/jenkins/ref/
RUN /usr/local/bin/plugins.sh /usr/share/jenkins/ref/plugins.txt

RUN git config --global credential.helper 'cache --timeout=18000'
/* config.groovy */
import jenkins.model.*

def jenkins = Jenkins.instance;
jenkins.setNumExecutors(5);
jenkins.setLabelString("linux docker");
# plugins.txt

# green balls
greenballs:1.15

# git
...
git:2.4.1

# worfklow-aggregator
...
workflow-aggregator:1.12

The DWS Jenkins image is based on the official Jenkins docker image. By default Jenkins will be listening on port 8080 but since this port is already in use by DWS backend, Jenkins is configured to listen on port 8888.

Next the config.groovy file is placed in /usr/share/jenkins/ref/init.groovy.d/. All files in this folder will be executed upon startup and can thus be used to configure Jenkins using its API. In this example the number of executors is set five and some labels are attached to the Jenkins machine. It is also possible to configure for instance the location of the Java and Maven installation if required as shown in this example.

All plugins that need to be installed can also be managed in a file which is copied into the image. All the dependencies listed in the file will be downloaded and installed on the Jenkins image by executing /usr/local/bin/plugins.sh.

At last git is configured to cache credentials. When Jenkins clones a repository it will use the credentials stored in the Jenkins credentials plugin. The first time the credentials are used git will cache them so they can later also be used to immediately push to the repository without passing the credentials again.

Maven Images

# build-maven.sh
docker build -t dws/mvn ../maven/base/
docker build -t dws/mvn-front-end ../maven/front-end/
docker build -t dws/mvn-e2e ../maven/e2e/
# Dockerfile dws/mvn
FROM maven:3-jdk-8

RUN mkdir -p /usr/src/dws
WORKDIR /usr/src/dws

ENTRYPOINT ["cat"]
# Dockerfile dws/mvn-front-end
FROM dws/mvn

RUN apt-get update && \
    apt-get install -y bzip2 make g++ && \
    git config --global url."https://".insteadOf git://

ENTRYPOINT ["cat"]
# Dockerfile dws/mvn-e2e
FROM dws/mvn-front-end

ENV DISPLAY=:1.0

RUN echo "deb http://packages.linuxmint.com debian import" \
        >> /etc/apt/sources.list && \
        apt-get update && \
        apt-get install -y --force-yes xvfb firefox

ENTRYPOINT ["Xvfb", ":1"]

Instead of installing all tools required to build the project on the Jenkins machine a set of docker images is created which contain the tools necessary. So instead of installing Java and Maven on the Jenkins machine in the Dockerfile a dws/mvn image is created which is based on the official Maven image. If a Maven task needs to be started on Jenkins a dws/mvn container is started in which the Jenkins workspace is mounted. Next the maven task is triggered in the container. This way only linux and docker are required on Jenkins or on the slave the build is executed on.

# Start Maven container
docker run -t -d --name mvn-container -v $currentDir/dws:/usr/src/dws dws/mvn

# Start Maven task in the container
docker exec mvn-container mvn -B versions:set -DnewVersion=1.0.0

For the DWS project a couple of such images are created.

  • dws/mvn
    This is the base Maven image which is based on the official Maven image and creates and sets the working directory. At last cat is executed to keep the container running when it is started with the options -t -d.
  • dws/mvn-front-end
    The Maven frontend image is based on dws/mvn and adds a couple of tools needed to run the build of dws-ui. When installing some npm modules bzip2, make and g++ are required.
  • dws/mvn-e2e
    This image is used to run the end-to-end tests. It is based on the dws/mvn-front-end image and adds Xvfb and Firefox. When starting this image it will start Xvfb.

Start jenkins

# start-jenkins.sh
source build-maven.sh

JENKINS_HOME="/var/jenkins_home/"

if [ ! -d $JENKINS_HOME ] 
then
    echo "Need password to create $JENKINS_HOME as mount point"
    sudo mkdir -p $JENKINS_HOME
    sudo chown 1000 $JENKINS_HOME
fi

docker network create -d bridge dws-jenkins

docker build -t dws/jenkins ../jenkins/
docker rm -vf dws_jenkins
docker run -d -p 8888:8888 \
           --net dws-jenkins \
           -v $JENKINS_HOME:/var/jenkins_home \
           -v /var/run/docker.sock:/var/run/docker.sock \
           -v $(which docker):/bin/docker \
           --name dws_jenkins dws/jenkins

Before starting Jenkins, first all Maven images are built. Next a local directory is created and the Jenkins user id is set as owner. Then the Jenkins network and image are created. The Jenkins image is started on the Jenkins network and the Jenkins home folder is mounted.

On the Jenkins machine we also need to have Docker to start docker containers such as mvn/dws. It would be possible to install Docker in the Jenkins docker container but this is not recommended. Instead the docker binary and docker socket of the host are mounted in the Jenkins container. When Jenkins now starts a docker container this container will be started as a sibling on its docker host instead of within Jenkins. To make docker work on Jenkins the root user is logged in on the Jenkins machine and lxc is installed in the Dockerfile.