Jenkins
Docker
CI/CD
DevOps
Automation

Jenkins running docker commands on a docker slave

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

If a Jenkins agent needs to run docker build, docker run, or similar commands, the agent must have both the Docker CLI and a usable Docker daemon connection. The key design question is where that daemon lives: on the host, inside the agent container, or on a remote Docker endpoint.

The Most Common Setup: Agent Uses the Host Docker Daemon

A common pattern is to run the Jenkins agent in a container but mount the host's Docker socket into it. Then Docker commands inside the agent control the host daemon.

Typical requirements are:

  • 'docker CLI installed in the agent image'
  • '/var/run/docker.sock mounted into the agent container'
  • correct permissions for the agent user

Example Docker run command for an inbound agent:

bash
docker run -d   --name jenkins-agent   -v /var/run/docker.sock:/var/run/docker.sock   my-jenkins-agent:latest

Inside that container, docker ps talks to the host daemon.

Jenkins Pipeline Example

Once the agent can reach Docker, the pipeline is straightforward.

groovy
1pipeline {
2    agent { label 'docker' }
3
4    stages {
5        stage('Build Image') {
6            steps {
7                sh 'docker version'
8                sh 'docker build -t my-app:ci .'
9            }
10        }
11    }
12}

The important part is not the Jenkinsfile itself. It is the agent configuration behind the docker label.

Permissions Matter

A frequent failure is:

text
Got permission denied while trying to connect to the Docker daemon socket

That usually means the agent user cannot access the mounted socket. Common fixes are:

  • run the agent as a user in the host Docker group
  • run the container with matching group ID for the socket
  • as a less desirable fallback, run the agent as root inside the container

The root fallback works, but it increases risk.

Docker-in-Docker Versus Docker-Outside-of-Docker

People often say "Docker slave" when they mean one of two different models.

Docker-Outside-of-Docker

This is the mounted-socket approach. The agent container uses the host Docker daemon.

Pros:

  • simple and fast
  • reuses host image cache
  • common in CI systems

Cons:

  • the agent effectively gets strong control over the host
  • isolation is weaker than it appears

Docker-in-Docker

This runs a Docker daemon inside the agent container itself.

Pros:

  • more isolated from the host daemon

Cons:

  • more operational complexity
  • nested storage and caching issues
  • often slower and harder to debug

For many Jenkins setups, mounted socket access is the practical choice, but it should be treated as privileged access.

Remote Docker Daemon Is Another Option

Instead of mounting the local socket, the agent can target a remote Docker host.

bash
export DOCKER_HOST=tcp://docker-builder.internal:2376

That can be useful when you want the Jenkins agent separated from the machine actually building images.

Agent Image Requirements

If your Jenkins agent runs in Docker, the image itself needs the tools your pipeline expects.

A minimal example Dockerfile:

dockerfile
1FROM jenkins/inbound-agent:latest
2USER root
3RUN apt-get update && apt-get install -y docker.io
4USER jenkins

Without the Docker CLI, even a mounted socket is useless.

Security Implications

Giving a Jenkins agent access to the Docker socket is effectively giving it high privilege over the host. A pipeline that can start containers, mount filesystems, or run privileged containers can often escape ordinary CI boundaries.

That does not mean the pattern is unusable. It means the agent should be treated as trusted infrastructure, not as a sandbox for untrusted jobs.

Common Pitfalls

A common mistake is installing the Docker CLI in the agent but forgetting to mount the socket or configure DOCKER_HOST.

Another mistake is assuming docker commands fail because of Jenkins, when the real problem is Linux socket permissions.

Developers also often call this a "Docker slave" problem when the real design issue is choosing between host-daemon access and true Docker-in-Docker.

Summary

  • A Jenkins agent can run Docker commands only if it has both the Docker CLI and daemon access.
  • The usual setup is an agent container with /var/run/docker.sock mounted from the host.
  • Socket permissions are one of the most common failure points.
  • Docker-in-Docker is possible, but more complex than using the host daemon.
  • Docker daemon access from CI is powerful and should be treated as privileged.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.