Setup Jenkins worker node that support building Docker Image.

Dong Nguyen
5 min readMar 8, 2023

Usually when we setup a Jenkins server, we usually use the master to build jobs. The master node is in charge of scheduling jobs, assigning slave nodes, and sending builds to slave nodes for execution. It will also keep track of the slave node state (offline or online), retrieve build results from slave nodes, and display them on the terminal output. This setup work but not recommended due to some security problem, the job ran on master can touch some sensitive on master node.

So in this post i will guide you to create a Jenkins worker node, this node is for building docker image. I assume that we already have a master node up and running. For me i already deployed it to.

https://c9fc-2405-4802-911d-4a10-cb5c-22f7-ca0e-f68a.ap.ngrok.io

As you can see that we only have master node, there is no agent beside this. To create new agent i will use docker compose. We will install docker, docker-compose. The worker node's architecture is same as.

Create a worker node on Console

From Jenkins UI, go to Dashboard > Manage Jenkins > Nodes and create a node.

I will name it copper. Choose Permanent Agent. Then click Create button. After that we need to edit some parameter, for me i will set Number of executors = 10

The agent will connect to master (controller) by websocket.

Then save and you will saw the manual show how to connect the agent to controller. Ignore it, we just need to grab the secret and host name.

Setup Agent using Docker Compose

The docker file is same as above. Remember to update your secret , host name and JENKINS_AGENT_NAME , make sure it match with the worker name.

version: "3.9"

networks:
default:
name: copper
driver: bridge

volumes:
agentworkdir:
dockercerts:


services:
docker:
image: docker:23.0.1-dind
volumes:
- dockercerts:/certs
- agentworkdir:/home/jenkins
privileged: true
environment:
DOCKER_TLS_CERTDIR: /certs
restart: always
agent:
build:
context: .
dockerfile: Dockerfile
environment:
JENKINS_SECRET: beec63a670cb8d7d8d119a358d0118acbee102a82c422f5d2172c28c7b1a1be6
JENKINS_AGENT_WORKDIR: /home/jenkins/agent
JENKINS_WEB_SOCKET: true
JENKINS_URL: https://c9fc-2405-4802-911d-4a10-cb5c-22f7-ca0e-f68a.ap.ngrok.io
JENKINS_AGENT_NAME: copper
DOCKER_HOST: tcp://docker:2376
DOCKER_CERT_PATH: /certs/client
DOCKER_TLS_VERIFY: 1
volumes:
- dockercerts:/certs
- agentworkdir:/home/jenkins
restart: always

In this compose file, we defined two services, the first one is docker:dind. Our agent will use this docker server to build image, start container with predefined image and so on.

Start docker by running docker compose up -d docker

Check docker log using docker compose logs -f docker to make sure it's running.

Next time we need to start agent by running docker compose up -d agent and also need to check the log of this service. The agent need to include docker cli it seft, we can do that define build block and using custom Dockerfile for agent.
The agent Dockerfile content is

FROM jenkins/inbound-agent
USER root
RUN apt-get update && apt-get install -y lsb-release
RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
https://download.docker.com/linux/debian/gpg
RUN echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
RUN apt-get update && apt-get install -y docker-ce-cli
USER jenkins
agent:
build:
context: .
dockerfile: Dockerfile
environment:
JENKINS_SECRET: beec63a670cb8d7d8d119a358d0118acbee102a82c422f5d2172c28c7b1a1be6
JENKINS_AGENT_WORKDIR: /home/jenkins/agent
JENKINS_WEB_SOCKET: true
JENKINS_URL: https://c9fc-2405-4802-911d-4a10-cb5c-22f7-ca0e-f68a.ap.ngrok.io
JENKINS_AGENT_NAME: copper
DOCKER_HOST: tcp://docker:2376
DOCKER_CERT_PATH: /certs/client
DOCKER_TLS_VERIFY: 1
volumes:
- dockercerts:/certs
- agentworkdir:/home/jenkins
restart: always

Start the agent service.

Check the log.

Verify the worker node

Go back to the web console, open Manage nodes and clouds you will see the worker node is active.

Test the worker node

I will create a Multibranch Pipeline job, in the Jenkinsfile i will update the lable to copper so it can run on the new worker node that we created.

The content of Jenkinsfile is like this

pipeline {
agent { node { label 'agent' } }
stages {
stage("Build") {
when {
beforeAgent true
anyOf {
branch "master"
buildingTag()
}
}
steps {
script {
checkout scm
IMAGE_TAG=BUILD_ID
if(env.TAG_NAME){
IMAGE_TAG = TAG_NAME
}
env.IMAGE_TAG = IMAGE_TAG
def image = docker.build("$JOB_BASE_NAME:$IMAGE_TAG","-f pipeline/Dockerfile .")
}
}
}
stage("Deploy") {
steps {
script {
if(env.TAG_NAME) {
env.TARGET_ENVIRONMENT = input message: "Which version do you want to deploy ?",
parameters:[
choice(name: 'TARGET_ENVIRONMENT', choices : ["staging","production"])
]
} else {
env.TARGET_ENVIRONMENT = "development"
}
checkout scm
sh """
echo "deploy to: $TARGET_ENVIRONMENT with tag ${env.IMAGE_TAG}"
"""
}
}
}
}
}

After pushing to code, it will triggered the Jenkins to scan respository then run the pipeline, and in the Console Output we can see that the job ran on copper worker node.

Let take a look to Build job, we can see that the docker build process is sucessfully.

That’s all, thank for reading.

--

--