# DinD (Docker in Docker)

### 🚧 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:

```bash
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).
    

```bash
docker run -d \
  --name dind \
  --privileged \
  --network jenkins-net \
  -e DOCKER_TLS_CERTDIR= "" \
  -p 2375:2375 \
  docker:dind
```

2. You configure your Jenkins container to point to this DinD container’s Docker daemon instead of the host's.
    
3. You set the `DOCKER_HOST` environment variable in your Jenkins container to the DinD container’s Docker socket, e.g.:
    
    ```bash
    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.
