Setting Up Jenkins with Docker Agent: A Step-by-Step Guide

Jasai HansdaJasai Hansda
9 min read

Introduction

Jenkins is a widely used automation server that enables continuous integration and continuous deployment (CI/CD). When deploying Jenkins inside a Docker container, a common requirement is to run pipelines that build and deploy containerized applications. This guide covers the proper configuration of a Jenkins Docker Agent, addressing permission issues, agent setup, and the use of Docker Pipeline Plugin for seamless builds.


Understanding Jenkins Controller & Agent Model

Jenkins operates on a master-agent model where:

  • The Jenkins Controller manages jobs, pipelines, and user interactions.

  • The Jenkins Agent executes the actual builds and runs jobs.

Using a Docker-based agent allows builds to run in isolated environments without affecting the Jenkins controller directly.


Setting Up Jenkins Inside a Docker Container

Run Jenkins (Controller) in Docker

Step 1. Install Docker

  • Ensure Docker is installed on your machine. You can download and install Docker from the official Docker website, or you can use this link to install docker in Linux.

Step 2. Run the Jenkins Container

Instead of running Jenkins with Docker access, we'll keep it isolated.

docker run -d --name jenkins \
  -p 8080:8080 -p 50000:50000 \
  --restart=on-failure \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

Explanation

  • -d: Run in detached mode

  • -p 8080:8080: Expose Jenkins UI

  • -p 50000:50000: Required for agent communication

  • -v jenkins_home:/var/jenkins_home: Persistent Jenkins data

Get the initial admin password:

 docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Copy the password from the terminal and paste it into the Jenkins setup page.


When building and deploying Docker containerized applications with Jenkins, security is a top concern. Many tutorials suggest running Jenkins with Docker access, but this can expose your system to severe security risks.

The best practice is to run Jenkins as a controller without Docker access and use a separate Jenkins agent that has controlled Docker permissions.
Just don’t include this in jenkins run command -v /var/run/docker.sock:/var/run/docker.sock which Grants Docker access to Jenkins.


Essential Jenkins Plugins for Enhanced Functionality

To maximize the capabilities of your Jenkins setup, consider installing the following essential plugins:

1. Docker Pipeline Plugin (Required)

  • Purpose: Enables Jenkins to interact with Docker containers directly within the pipeline scripts.

  • Installation: Go to Manage JenkinsManage PluginsAvailable tab, search for "Docker Pipeline", and install.

2. Git Plugin (Required)

  • Purpose: Integrates Git version control with Jenkins, allowing you to pull code from repositories.

  • Installation: Go to Manage JenkinsManage PluginsAvailable tab, search for "Git Plugin", and install.

3. Pipeline: Stage View Plugin (best view)

  • Purpose: Provides a detailed view of the pipeline stages, making it easier to track progress and debug issues.

  • Installation: Go to Manage JenkinsManage PluginsAvailable tab, search for "Pipeline: Stage View", and install.

4. Blue Ocean Plugin

  • Purpose: Provides a modern and user-friendly interface for Jenkins, making it easier to visualize and manage pipelines.

  • Installation: Go to Manage JenkinsManage PluginsAvailable tab, search for "Blue Ocean", and install.

5. Credentials Binding Plugin

  • Purpose: Allows you to securely manage and use credentials within your Jenkins pipelines.

  • Installation: Go to Manage JenkinsManage PluginsAvailable tab, search for "Credentials Binding", and install.

By installing these plugins, you can enhance the functionality, security, and usability of your Jenkins environment, making it more robust and efficient for your CI/CD workflows.


Connect the Agent to Jenkins

Configuring a Jenkins Agent in the UI and Understanding Its Setup

When you configure an agent in Jenkins UI, you are setting up a remote machine or container that will execute your Jenkins jobs. Let's break down what happens at each step, what the configuration means, and the required permissions.

Step 1: Navigate to Agent Configuration

  1. Go to Manage JenkinsManage Nodes and Clouds

  2. Click New Node

  3. Enter the agent's name (e.g., DockerAgent)

  4. Select Permanent Agent and click OK


Step 2: Configure the Agent Settings

You'll now see several fields to configure:

1. Number of Executors: 1

This determines how many concurrent jobs the agent can run. If your agent has sufficient CPU and RAM, you can increase this number.

2. Remote Root Directory: /home/jenkins (imp)

  • This is the working directory for Jenkins on the agent.

  • Jenkins will store job workspaces, logs, and agent configurations here.

  • If it does not exist, Jenkins will attempt to create it when the agent starts.

What Happens in /home/jenkins?

Once the agent starts:

  • It downloads necessary files from the controller.

  • Jenkins stores job workspaces and logs.

  • When a pipeline runs, build scripts execute in this directory.


Grant the Correct Permissions

  • If you want to avoid permission issues, manually create the folder before running the agent.

  • The Jenkins user (inside Docker or on the host) must have read/write access to /home/jenkins.

  • If permission errors occur, fix them with:

Try the following steps:

Step 1: Create the Agent Work Directory Manually

Run this command on your terminal:

sudo mkdir -p /home/jenkins #create folder

Step 2: Change Ownership

Give the jenkins or the correct user permissions to access the directory:

sudo chown -R jenkins:jenkins /home/jenkins #Sets the owner to Jenkins #Sets the owner to Jenkins

Alternatively, if you're using a different user:

sudo chown -R $(whoami):$(whoami) /home/jenkins

Step 3: Set Correct Permissions

Allow Jenkins to read and write to this directory:

sudo chmod -R 755 /home/jenkins

Check the permission to access /home/jenkins

ls -ld /home/jenkins

3. Launch Method: Launch agent by connecting it to the controller

  • This launch method means that the Jenkins agent (worker node) will actively connect to the Jenkins controller (master node) rather than the controller initiating the connection.

  • This is ideal for Docker-based agents.

How does the connection work?
  1. The Jenkins controller provides a secret key and connection details for the agent.

  2. The agent node runs a command using java -jar agent.jar to establish a connection to the controller.

  3. Once connected, the agent listens for tasks from the controller and executes build jobs.

Save these configuration settings and start the agent.

The agent has connected, but we might have a space issue like this (Let's fix it).

  • This issue isn't caused by Jenkins; it's due to limited storage in the /tmp folder on EC2 resources because it is being used. So, let's increase the space.

  • Check the disk space

        df -h
    

  • To increase the size of the /tmp folder, use this command to edit the fstab file.

      vi /etc/fstab
    

The original file looks something like this:

  • Add this line to the file and save it

      tmpfs /tmp tmpfs size=4G 0 0
    

  • Now remount the /tmp file, and you will see the increased space.

      mount -o remount /tmp
    

  • Space issue Fixed


Step 3: Start the Agent

Where Can You Run the Agent?

You can run the agent on any server that has network access to the Jenkins controller.
There are two common scenarios:

✅ Scenario 1: Running the Agent on the Same Instance as the Jenkins Controller

  • If the Jenkins controller and agent are running on the same server instance, you can run:

      java -jar agent.jar -url http://localhost:8080/ -secret <SECRET_KEY> -name "docker-agent" -webSocket -workDir "/home/jenkins"
    
  • This approach reduces networking complexity, but it doesn't scale well if multiple builds are running.


✅ Scenario 2: Running the Agent on a Different Server Instance

  • If you want to separate the agent from the controller, you can run it on another server instance.

  • The agent must be able to communicate with the Jenkins controller's public/private IP.

Example:

java -jar agent.jar -url http://<JENKINS_CONTROLLER_PUBLIC_IP>:8080/ -secret <SECRET_KEY> -name "docker-agent" -webSocket -workDir "/home/jenkins"

Requirements:

  • The agent must have Java installed.

      wget https://download.oracle.com/java/17/archive/jdk-17.0.11_linux-x64_bin.rpm
      sudo yum install -y jdk-17.0.11_linux-x64_bin.rpm
    
  • The Jenkins controller must allow inbound connections from the agent EC2 (port 8080 open in Security Groups).

  • The agent EC2 instance must have internet access if the controller is hosted externally.

Which is the Best Approach?

  • For small setups, running the agent on the same EC2 instance as the controller is fine.

  • For production setups, running the agent on a separate EC2 instance is better for scalability and prevents builds from slowing down the controller.

  • 🚀 For larger workloads, using Kubernetes or Dockerized Jenkins agents is recommended.


Final Steps: Verify Agent Connection and Build Pipeline

  1. In Jenkins UI, go to Manage Jenkins → Manage Nodes and Clouds

  2. Check if the agent (DockerAgent) is online

  3. Run a sample pipeline to confirm execution.

Write a Secure Jenkins Pipeline

Now, we’ll create a Jenkins pipeline that builds and runs a Docker container.

1. Create a New Pipeline Job

  • Go to Jenkins Dashboard → Click New Item

  • Select Pipeline → Click OK

2. Add the Pipeline Script

  • Add the script directly by choosing Pipeline Script or use the Pipeline from SCM option if your script is stored in a version control system.

pipeline {
    agent { label 'DockerAgent' }  // Run only on the secure agent

    environment {
        IMAGE_NAME = "dockerimg"
        CONTAINER_NAME = "MyApp"
    }

    stages {
        stage('Checkout Code') {
            steps {
                git branch: 'main', url: 'https://github.com/Jasai007/Flask-DevOps-Toolkit.git'
            }
        }

        stage('Install Dependencies and Run Tests') {
            steps {
                sh '''
                    # Install dependencies without cache to avoid permission issues
                    pip install --no-cache-dir -r requirements.txt
                    # Run unit tests
                    python3 -m unittest -v test.py
                '''
            }
        }

        stage('Build Docker Image') {
            steps {
                sh 'docker build -t $IMAGE_NAME .'
            }
        }

        stage('Run Container') {
            steps {
                sh '''
                    docker stop $CONTAINER_NAME || true
                    docker rm $CONTAINER_NAME || true
                    docker run -d -p 80:80 --name $CONTAINER_NAME $IMAGE_NAME
                '''
            }
        }
    }
}

Click Save and Build Now 🚀.

3. Built Pipeline Result


Why This is Secure?

ApproachSecurityDocker BuildsRecommended?
Jenkins runs inside Docker with /var/run/docker.sockRisky (Jenkins can control the host)✅ Yes⚠️ No
Jenkins runs inside Docker with Docker-in-Docker (DinD)⚠️ Less secure✅ Yes, but slow⚠️ No
Jenkins with a separate Docker-enabled agentBest security✅ YesYes (Best practice)

Best Practices for Secure Jenkins + Docker Setup

Use a separate agent for running Docker builds.

Ensure agent has correct permissions (chown jenkins:jenkins).

Limit Jenkins Docker access (use rootless Docker for security).

Keep Jenkins & plugins updated (Manage Jenkins → Plugin Manager).

Use Multi-Stage Docker Builds to optimize image sizes.


Conclusion

We have now set up Jenkins in Docker, configured a secure agent with Docker access, and created a safe and efficient CI/CD pipeline.

By following this guide, you can set up a secure and scalable Jenkins pipeline with Docker agents, properly handle permission issues. This setup ensures efficient, containerized CI/CD workflows that align with industry best practices.

0
Subscribe to my newsletter

Read articles from Jasai Hansda directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jasai Hansda
Jasai Hansda

Software Engineer (2 years) | In-transition to DevOps. Passionate about building and deploying software efficiently. Eager to leverage my development background in the DevOps and cloud computing world. Open to new opportunities!