Deploying Jenkins Docker Agents
Jenkins is ok. It's got the support of a huge swath of plugins, but leaves it up to you to figure out anything but Golden Path deployments. What I wanted was a Jenkins Agent in a Container that was able to handle the deployment of other containers on the Docker host.
This article elaborates on a lot of the issues that plague the Jenkins Agent docker image, but misses some of the steps to finally get you to your destination.
Prerequisites
Install Jenkins Plugins
Log in to your Jenkins console. Install the Docker Commons and Docker Pipeline plugins.
Prestage the Docker Agent
From your Jenkins console, go to Manage Jenkins -> Nodes. Add a new Node, making it a "Permanent Agent" type. After creation, specify the following to mandatory parameters:
- Remote root directory ->
/home/jenkins/agent - Launch Method ->
Launch agent by connecting it to the controller
Select the newly created agent, and copy one of the command line configurations. We'll need the the following later:
- The Jar URL
- Docker Agent Name
- The Secret
- The Infom Url
For example, the following Unix installation steps:
curl -sO {JAR_URL_TO_SAVE}
java -jar agent.jar -url {INFORM_URL_TO_SAVE} -secret {SECRET_TO_SAVE} -name "{NAME_TO_SAVE}" -workDir "/home/jenkins/agent"Docker Setup
Obtain GID
Connect to the Docker host you will be installing the Jenkins Agent on. Obtain the GroupID (GID) of the Docker group by running getent group docker .
Create Dockerfile
Create a file called Dockerfile on the Docker host. Use the following content for the file. Replace the URL on line 4 with the JAR_URL, and replace the number on line 6 with the GID obtained previously
FROM jenkins/inbound-agent
USER root
RUN apt update && curl -fsSL https://get.docker.com | sh
RUN curl -sO {JAR_URL}
RUN usermod -aG docker jenkins
RUN groupmod -g 993 docker
USER jenkinsCreate the Image
Run the following command to build the image from the docker file.
docker image build -f jenkins-agent.Dockerfile -t jenkins-agent:custom .
Run the Image
Run the following command to deploy the agent. Replace the INFORM_URL with the inform URL saves earlier, replace the SECRET with the secret saved earlier, and replace the NAME with the name saved earlier.
docker run -d -v /var/run/docker.sock:/var/run/docker.sock --init jenkins-agent:custom -url {INFORM_URL} -workDir=/home/jenkins/agent -secret {SECRET} -name "{NAME}"
Consult the docker container logs if it is not running: docker logs {container_id}
Validate
Refresh the status of the newly created Jenkins Agent, it should be connected.
Pipeline Configuration
Ensure any pipelines specify the docker tools, so that the Jenkins agent has the commands available to interact directly with the Docker host.
Configure Docker Tools
In Jenkins, to go Manage Jenkins -> Tools. Navigate "Add Docker". Provide a Name, which will be used later, select "Install Automatically". Select "Add Installer", then select "Download from Docker.com". Save the page.
Specify Docker Tools in Pipelines
When using the agent, specify the tools installation, and provide the name of the DockerTools created earlier. See Example:
pipeline {
agent { label 'docker-prod'}
tools {
dockerTool '{NAME}'
}
stages {
stage('Build') {
steps {
sh 'unset DOCKER_HOST'
sh 'docker ps'
}
}
}
}The example above runs unset DOCKER_HOST . This is precautionary to ensure the Docker agent utilizes the Docker socket instead of hostname and port.
Deploying code to multiple hosts
There are likely better ways to do this that scale, but I'm ok maintaining 1:1 relationship between agents and hosts.
pipeline {
agent none
stages {
stage('Build to Hosts') {
parallel {
stage('Docker-01'){
agent { label 'docker-prod-01'}
tools {
dockerTool 'docker'
}
stages{
stage('Build'){
steps {
sh 'unset DOCKER_HOST'
sh 'docker build -t ghost_prod:latest .'
}
}
}
}
stage('Docker-02') {
agent { label 'docker-prod-02'}
tools {
dockerTool 'docker'
}
stages {
stage('Build'){
steps {
sh 'unset DOCKER_HOST'
sh 'docker build -t ghost_prod:latest .'
}
}
}
}
}
}
}
}