DinD (Docker in Docker)

NaveenKumar VRNaveenKumar VR
3 min read

🚧 Problem Statement

Imagine you're running a Jenkins server inside a Docker container. Everything works fine—until your CI pipeline tries to execute docker build or docker push. Suddenly, your workflow fails. But why

🔍 Root Cause

Docker commands like build or push are executed by the Docker daemon (dockerd), which is the core engine of Docker running on the host system. Communication with this daemon happens through a Unix socket called docker.sock.

When a Docker client (like the Jenkins container) sends a command, it’s routed via docker.sock to the Docker daemon, which performs the actual operation and returns the result.

Here’s the catch: you cannot run the Docker daemon itself inside a Docker container in the traditional way. Why? Let’s break it down.

❓ Why Can’t You Run Docker Daemon Inside a Docker Container in Straight Forward approach ?

The Docker daemon needs deep access to the host system—including the kernel and several privileged operations that aren’t typically available inside a container. Since containers are isolated environments sharing the host's kernel, running a full Docker server inside another container breaks this isolation model and leads to permission and capability issues.

In short:

  • Docker requires host-level access.

  • Containers are not meant to emulate full virtual machines.

  • Running dockerd inside a container is not straightforward and can introduce security and stability risks.

✅ Solution

From our earlier discussion, we learned that Docker commands need to be routed through docker.sock, which communicates with the Docker daemon. Since docker.sock is part of the Docker server component running on the host, we must tell our application container—like Jenkins—how to access it.

There are two common approaches to enable Docker commands from inside a container:

🔗 1. Mounting the Host’s Docker Socket

In this approach, we directly mount the host’s docker.sock into the Jenkins container:

docker run -d \
  --name jenkins-docker \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  jenkins/jenkins:lts

This allows Jenkins to communicate with the host's Docker daemon just as if it were running natively on the host.

Pros:

  • Simple to set up.

  • No need to run another Docker daemon.

Cons:

  • Security risk: You're giving full control of the host’s Docker engine to the container.

  • If compromised, the Jenkins container can perform any operation on your host, including modifying or deleting containers and images.

🐳 2. Using a Docker-in-Docker (DinD) Container

A more secure and isolated approach is to use a Docker-in-Docker (DinD) container. This is a special Docker image that runs its own Docker daemon inside a container.

Here's how it works:

  1. You run a DinD container (based on the official docker:dind image).
docker run -d \
  --name dind \
  --privileged \
  --network jenkins-net \
  -e DOCKER_TLS_CERTDIR= "" \
  -p 2375:2375 \
  docker:dind
  1. You configure your Jenkins container to point to this DinD container’s Docker daemon instead of the host's.

  2. You set the DOCKER_HOST environment variable in your Jenkins container to the DinD container’s Docker socket, e.g.:

     docker run -d \
       --name jenkins-docker \
       --network jenkins-net \
       -p 8080:8080 \
       -p 50000:50000 \
       -v jenkins_home:/var/jenkins_home \
       -e DOCKER_HOST=tcp://dind:2375 \
       jenkins/jenkins:lts
    

-e DOCKER_HOST=tcp://dind:2375: Tells Jenkins to send Docker commands to the DinD container (hostname dind on port 2375).

Pros:

  • Isolates Docker operations from the host.

  • Limits Docker access to the DinD environment only.

  • Safer for shared or multi-tenant CI setups.

Cons:

  • Slightly more complex to set up.

  • Performance overhead compared to using the host daemon.

  • Security concerns still exist (DinD requires privileged mode), but it's safer than exposing the host’s socket.

  • This setup disables TLS and runs the DinD container in privileged mode. That’s fine for testing, learning, or internal CI setups, but not recommended for production.

📌 Important Note: Make sure both the Jenkins container and the DinD container are running on the same Docker network so they can communicate.

0
Subscribe to my newsletter

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

Written by

NaveenKumar VR
NaveenKumar VR