Jenkins in Docker: run Docker inside a Jenkins container

Jenkins in Docker: run Docker inside a Jenkins container

Set up Jenkins in Docker and enable the Jenkins container to build, run, and push Docker images by bind-mounting the host Docker socket. Step-by-step guide.

Jenkins is an open-source CI/CD tool with a large plugin ecosystem for automating builds, tests, and deployments. Running Jenkins inside a Docker container solves configuration file conflicts that occur when multiple projects share a Jenkins installation on the same host.

The new challenge that creates: if you want to build and push Docker images from within Jenkins, the Jenkins container needs access to Docker. This article covers how to set that up using a custom Jenkins image that bind-mounts the host's Docker socket into the container.

The source code and Dockerfile for the NodeJS application used in this tutorial are on GitHub.

Prerequisites

  • Working knowledge of Docker and the terminal
  • A Docker Hub account

Why not Docker-in-Docker?

The most common suggestion for running Docker inside a container is Docker-in-Docker (DinD) — running a Docker daemon inside the Jenkins container itself. The original DinD approach required the -privileged flag, which gives the container full access to the host kernel and introduces security risks including data corruption when multiple containers share /var/lib/docker.

Modern alternatives like rootless containers and tools such as sysbox address some of these issues, but for a straightforward CI use case, bind-mounting the host Docker socket is simpler, more stable, and does not require elevated privileges.

Create a custom Jenkins image

Create a Dockerfile with the following content:

FROM jenkins/jenkins:lts
USER root

RUN apt-get update -qq && \
    apt-get install -y ca-certificates curl && \
    install -m 0755 -d /etc/apt/keyrings && \
    curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc && \
    chmod a+r /etc/apt/keyrings/docker.asc && \
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
    https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
    > /etc/apt/sources.list.d/docker.list && \
    apt-get update -qq && \
    apt-get install -y docker-ce docker-ce-cli containerd.io

RUN usermod -aG docker jenkins

What each section does:

  • FROM jenkins/jenkins:lts uses the official long-term support Jenkins image as the base
  • The RUN block installs Docker using the current recommended method from Docker's official documentation — downloading the GPG key into /etc/apt/keyrings and adding the Docker apt repository
  • usermod -aG docker jenkins adds the Jenkins user to the docker group so it can run Docker commands without sudo

Build the image:

docker image build -t custom-jenkins-docker .

Run the Jenkins container

Run the custom image with two volume mounts:

  • /var/run/docker.sock:/var/run/docker.sock — binds the host Docker daemon socket into the container, giving the Jenkins Docker CLI a daemon to talk to
  • jenkins_home:/var/jenkins_home — persists Jenkins configuration and job data across container restarts
docker run -it -p 8080:8080 -p 50000:50000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v jenkins_home:/var/jenkins_home \
  custom-jenkins-docker

Visit http://localhost:8080 to complete the Jenkins setup.

Configure Jenkins

The setup wizard asks for an initial admin password. Retrieve it from the container logs printed after the docker run command.

Jenkins getting started page

Initial admin password in container logs

Select Install suggested plugins when prompted.

Jenkins plugin installation screen

Create your admin user and finish the setup wizard.

Jenkins admin user creation

Dockerize a Node.js app with Jenkins

Install required plugins

Go to Manage Jenkins → Manage Plugins → Available and install:

  • NodeJS Plugin — enables Node.js build steps
  • CloudBees Docker Build and Publish plugin — builds Dockerfiles and pushes images to Docker Hub

Jenkins plugins manager

Configure the NodeJS plugin

Go to Manage Jenkins → Global Tool Configuration and add a NodeJS installation.

NodeJS global tool configuration

Create a build job

On the Jenkins dashboard, click New Item, select Freestyle project, give it a name, and click OK.

Jenkins new item - freestyle project

Under Source Code Management, select Git and enter the repository URL: https://github.com/Kikiodazie/Backend-RESTful-API.git

Leave Credentials blank — the repository is public.

Jenkins SCM configuration with GitHub URL

Under Build, add a Docker Build and Publish build step.

Jenkins Docker Build and Publish step

Set the Repository Name to your_dockerhub_username/your_repo_name, for example kikiodazie/node-docker.

Leave Registry credentials blank for now — authentication is handled in the next step.

Docker Build and Publish repository name field

Authenticate with Docker Hub inside the container

The Jenkins container needs to be logged into Docker Hub to push images. Get a shell inside the running container:

docker exec -it <container_name_or_id> /bin/bash

Inside the container, log in to Docker Hub:

docker login

Enter your Docker Hub credentials when prompted.

Docker Hub login inside Jenkins container

Run the build

Back in Jenkins, click Build Now. Jenkins will clone the repository, build the Docker image from its Dockerfile, and push it to your Docker Hub account.

View the output in Build History → Console Output.

Jenkins build console output

Successful Docker build and push in Jenkins

The image is now built and published to Docker Hub from inside the Jenkins container.

Where to go next

From here you can add build triggers on GitHub push events using a webhook, parameterize the repository name and Docker Hub credentials as Jenkins environment variables, or extend the pipeline to run tests before the Docker build step. The Jenkins Docker installation documentation covers additional configuration options including HTTPS and agent setup.

FAQs

1, What is the difference between Docker-in-Docker and bind-mounting the Docker socket?

Docker-in-Docker runs a full Docker daemon inside the container, which historically required the -privileged flag and introduced security and data corruption risks. Bind-mounting the host socket (/var/run/docker.sock) gives the container's Docker CLI access to the host daemon directly — no privileged mode required, no separate daemon to manage.

2, Why do I need a custom Jenkins image instead of the official one?

The official jenkins/jenkins:lts image does not include Docker. The custom image adds Docker CE to the Jenkins base image and adds the Jenkins user to the Docker group, which is what enables Jenkins to run Docker commands as part of a build job.

3, What does usermod -aG docker jenkins do?

It adds the jenkins user to the docker group. On Linux, the Docker daemon socket is owned by the docker group. Without this, the Jenkins user cannot communicate with the socket and all Docker commands in build jobs will fail with a permissions error.

4, Is bind-mounting the Docker socket secure?

It gives any process inside the container the same access to the Docker daemon as the host user running the container, which means a compromised build job could affect other containers or the host. For production CI environments, use dedicated Docker-in-Docker solutions with appropriate isolation, or a remote Docker daemon with TLS authentication.

5, Can I use this setup with a Jenkins pipeline instead of a freestyle project?

Yes. Once the custom image is running with the socket bind-mount, you can use Docker commands in both freestyle build steps and declarative or scripted Jenkinsfile pipelines. The docker CLI is available in the container regardless of how Jenkins invokes it.

About author

Consistency is key. That’s what Divine believes in and he says he benefits from that fact which is why he tries to be consistent in whatever he does. Divine is currently a Developer Advocate and Technical Writer who spends his days’ building, writing, and contributing to open-source software.days

Book A Call!

Reach Your Technical Audience And Drive Product Adoption.

We are engineers, developer advocates, and marketers passionate about creating lasting value for SaaS teams. Partner with us to create the human-written developer marketing, SEO, demand-gen, and documentation content.

Get started

*35% less cost, risk-free, no lock-in.

Logo 1
Logo 2
Logo 3
Logo 4
Logo 5
Logo 6
Logo 7
Logo 8
Logo 9
Logo 10
Logo 11
Logo 12
Logo 13
Logo 14
Logo 15
Logo 16
Logo 17
Logo 18