How to use Docker containers as build agents(Nodes) in Jenkins

How to use Docker containers as build agents(Nodes) in Jenkins

If you install Jenkins for the first time, you will notice that you get a message at the top mentioning that you need to enable Nodes for security purposes.

In my previous builds of Jenkins, these have always been separate VM's running their own OS etc. Recently I have made the move over to Docker, and instead, I want to host the entire stack in Docker.

This guide will show you have to create Docker Jenkins agents to use as nodes. These nodes will spin up and down in docker as required.

Before you start, this guide assumes that the following is up and running in the first place.

  • Jenkins Master - mine is running in Docker
  • the Docker Plugin for Jenkins is installed
  • a Docker Host setup and running
  • a test build job

Installing the Docker Plugin

We need to install the Docker plugin so that can have Jenkins spin up and down as many hosts as it needs, based on the number of build jobs running. The Docker plugin enabled the Jenkins master server to do this.

  1. Go to Manage Jenkins, then click on Manage Plugins.

2. Go to Available and search Docker in the search box. Select Docker and click on Install without restart.  

3. Once installed restart Jenkins Master server. In my case, it's just a simple docker-compose down && docker-compose up -d.

Build Image for Docker Agent

Next, we need to create an image that implements a couple of prerequisites, SSHD and Java.

SSHD Config File

We need to create a config file for the Dockerfile which we will use shortly. Create a new file called sshd_config. Inside this file copy the following;

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

Dockerfile

Next, we need to create a simple Dockerfile that will facilitate our Jenkins agent. Each time Jenkins Master server goes running a build job, it will grab this docker image and spin up another container to run it and then stop and remove it once it's finished.  

Create a new file called Dockerfile and copy the following into the file;

Basic Dockerfile

FROM ubuntu
RUN mkdir -p /var/run/sshd
RUN 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_config
RUN echo root:mysecretpassword | chpasswd
CMD ["/usr/sbin/sshd", "-D"]

Advanced Dockerfile

The below example builds upon the above Dockerfile but also includes PowerShell and Git.

FROM ubuntu
RUN mkdir -p /var/run/sshd
RUN apt -y update
RUN apt install -y openjdk-8-jdk
RUN apt install -y openssh-server
RUN apt install -y git wget apt-transport-https software-properties-common
RUN wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt -y update
RUN add-apt-repository universe
RUN apt install -y powershell
RUN ssh-keygen -A
ADD ./sshd_config /etc/ssh/sshd_config
RUN echo root:mysecretpassword | chpasswd
CMD ["/usr/sbin/sshd", "-D"]

This dockerfile does a number of things like installs Java and the OpenSSH-Server aptitude packages but also set the root password. Ideally, you could implement a secret here.

Build the Docker Agent image

We will need to run the following docker command to build the image.

docker image build --no-cache -t docker-agent .

We can also test the image after a successful build by running the following command;

docker run -d -ti -p 43498:22 docker-agent:latest

Finally, do a quick test to see if you can ssh into the container now using root as your username and the password you set.

ssh root@localhost -p 43498

If you can successfully do those things, you can move onto the next section.

Configure Jenkins Docker Agent

  1. Inside Jenkins, click on Manage Jenkins, Configuration, and click on Configure Clouds.

2. Next we need to connect Docker. Click on Add a new cloud and select Docker.

3. Give it a name, I gave mine Jenkins Agent.

4. Click on Click on Docker Cloud details...

Configure the following values:

Name Value
Docker Host URI tcp://IP-of-Docker-Host:2375
▢ Enabled Tick ▣ Enabled
Expose DOCKER_HOST Tick ▣
Container Cap 4

Adjust your container cap based on the number of build jobs you are running. I'm not a very heavy user of Jenkins yet, so 4 containers should be more than enough.

Lastly, before we move on to the next part, we need to validate that we can communicate to the docker host. Click on Test Connection and make sure that it returns a version number.

Docker Agent Template

Next, we need to set the parameters on how Jenkins interacts with Docker and creates the agents.

Click on Docker Agent templates...

Copy the following values;

Name Value
Labels docker-agent
Enabled Yes
Name docker-agent
Docker Image docker-agent
Remote File System Root /root/jenkins
Connect Method Connect with SSH - Add your root credentials to Jenkins from the Dockerfile here.

Node Properties / Tool Locations / Docker Agent templates

Name Value
Name (Git) Default
Home /usr/bin/git

Click on Save and that's it. You should be up and running.

For use to test this out, we need to do one more thing to our test build job. Open up the Configure page of the test build, and make sure to select the following;

Setting this, make Jenkins only use the docker agent to build this job.