Container as a build slave

How to Configure Docker Container as Build Slaves for Jenkins

Naren Chejara

--

Jenkins is one of the prominent open-source tools for continuous integration. Recently, I started learning Jenkins to shorten the release cycle of product development and decided to write stories for the people who are learning Jenkins like me.

Today, we are going to learn how to configure or set up docker containers as build slaves for Jenkins. The basic knowledge of Jenkins and docker are prerequisites for this story but it is not mandatory as I tried my best to explain everything in detail so the beginner can leverage this story.

Let's get started!

We need the following ingredients to make the Build slaves recipe for Jenkins

  1. Jenkins Master Machine
  2. Docker Plugin for Jenkins
  3. Docker Host
  4. Build Image for Docker Agent
  5. Configure Docker & Agent
  6. Freestyle Jenkins Job
  7. Build/Trigger The Job
  8. Troubleshoot

Jenkins Master

We need to install and run Jenkins — you can refer to my Jenkins Installation story in order to install Jenkins on the Ubuntu machine.

For other OS, you can follow the download page from the Jenkins official website. I have installed Jenkins on Windows 10 machine for this story.

Docker Plugin

I am using the docker plugin to run jobs in container slaves, therefore, we need to install the “Docker” plugin.

Install docker plugin

  • Go to Manage Jenkins -> Manage Plugins
  • Go to “Available” Tap and search “Docker” in the search box
Plugin Manager
  • Restart the Jenkins

Docker Host

Docker Host is nothing but a machine that will be used to launch containers requesting from the Jenkins Master. Jenkins will communicate with the docker host using remote API which means docker remote API should be enabled prior to configuring docker cloud and agent in the Jenkins.

I am using Docker-Toolbox, You can refer to this story if you aren’t using docker-toolbox.

Let’s enable remote docker API in Docker Toolbox. You can refer to the Docker Toolbox installation article if it hasn’t been installed yet on the machine.

Enable Remote Docker API

  • Run the “Docker Quickstart Terminal” (You will get this terminal after docker-toolbox is installed successfully)
Docker-Toolbox
  • SSH to docker-machine
$ docker-machine ssh //ssh to docker machine
  • Alter TLS setting in the profile file to make sure we switch to a non-TLS port
$ sudo vi /var/lib/boot2docker/profile
profile

Alter DOCKER_TLS from “auto” to “no”. Save the changes and exit from the SSH session.

Restart the machine to make sure the changes applied

$ docker-machine restart
  • Get host IP
$ docker-machine ip
//output
192.168.99.100
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.5","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"2019-11-13T07:28:45.000000000+00:00","Experimental":"false","GitCommit":"633a0ea838","GoVersion":"go1.12.12","KernelVersion":"4.14.154-boot2docker","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"v1.2.10","Details":{"GitCommit":"b34a5c8af56e510852c35414db4c1f4fa6172339"}},{"Name":"runc","Version":"1.0.0-rc8+dev","Details":{"GitCommit":"3e425f80a8c931f88e6d94a8c831b9d5aa481657"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.5","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"633a0ea838","GoVersion":"go1.12.12","Os":"linux","Arch":"amd64","KernelVersion":"4.14.154-boot2docker","BuildTime":"2019-11-13T07:28:45.000000000+00:00"}

Build Image for docker Agent

Docker plugin has the following prerequisites in order to communicate with the container so we will create a docker image with the following packages

  1. Docker image must have SSHD installed
  2. Docker image must have JAVA installed

The container slaves are used to execute operations that may require project installation and its dependencies such as java, GIT, Maven, etc., therefore, it is suggested to create a docker image with all your project dependencies along with SSHD & JAVA packages.

Let’s build a new image from scratch.

SSHD Config File

Create a ‘sshd_config’ file and copy/paste the below SSHD configuration settings into the file.

Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
LoginGraceTime 120
PermitRootLogin yes
PubkeyAuthentication yes
UsePAM yes

Create a Docker File

Create a docker file (Dockerfile) and copy/paste the following commands in it and build an image

FROM ubuntuRUN mkdir -p /var/run/sshdRUN apt -y update
RUN apt install -y openjdk-8-jdk
RUN apt install -y openssh-server
RUN ssh-keygen -A
ADD ./sshd_config /etc/ssh/sshd_configRUN echo root:password123 | chpasswdCMD ["/usr/sbin/sshd", "-D"]

Above code, snippet does the following

  • Create a privilege separation directory for SSHD services
  • Install open JDK and OpenSSH-server packages
  • Generate keys like RSA, DSA, ECDSA, ed25519 on the default location i.e. /etc/ssh/
  • Add ‘sshd_config’ to ‘/etc/ssh/sshd_config’
  • Read username: password from the stdin and update it on /etc/passwd
  • Start SSDH services

Build an image

Run the command below in order to build the image from the docker file

$ docker image build -t docker-slave .

Launch a Container

$ docker run -d -ti -p 38787:22 docker-slave:latest

Test SSH Connection

$ ssh root@<machine_ip> -p 38787

Configure Docker & Agent

It’s time to configure the docker cloud and docker agent template. Go to Manage Jenkins → Configuration → Add a new Cloud → docker

Add a new cloud Setting

Configure Docker Cloud Details

Configure Docker Agent Templates

Freestyle Jenkins Job

We have configured & prepared most of the groundwork, let’s create a freestyle job and restricted it to trigger on ‘docker-slave-demo’ labeled slave. Read this story if you are to learn how to create a freestyle job and clone the GIT repository.

Build The Job

Finally, we have configured everything, Let’s trigger the build by hitting the ‘Build Now’ link from the left navigation menu. The job will launch a container and clone the repository from Github.

Troubleshoot

Error 1: The client sent an HTTP request to an HTTPS server

Solution: Alter DOCKER_TLS setting from “auto” to “no” from /var/lib/boot2docker/profile file and restart the docker services

Error 2: pending — There are no nodes with the label ‘docker-slave-demo

Solution: This means a problem in container launching, you can go to Manage Jenkins → System Logs and check the error logs

If you enjoyed this story, please hit the like button and share it to help others find it.

--

--