> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-integration/3.0/use-harness-ci/use-harness-ci/manage-dependencies/run-docker-in-docker-in-a-ci-stage.md).

# Run Docker-in-Docker in a Build stage

You can run Docker-in-Docker as a Background step in a Build stage.

CI pipelines that use a [Kubernetes cluster build infrastructure](/continuous-integration/3.0/use-harness-ci/use-harness-ci/set-up-build-infrastructure/k8s-build-infrastructure.md) need Docker-in-Docker (DinD) if you need to run Docker commands as part of the build process. For example, if you want to build images from [two separate codebases in the same pipeline](/continuous-integration/3.0/use-harness-ci/use-harness-ci/codebase-configuration/clone-and-process-multiple-codebases-in-the-same-pipeline.md): One with a [Build and Push to Docker step](/continuous-integration/3.0/use-harness-ci/use-harness-ci/build-and-upload-artifacts/build-and-push/build-and-push-to-docker-registry.md) and another with Docker commands in a [Run step](/continuous-integration/3.0/use-harness-ci/use-harness-ci/run-step-settings.md).

To configure DinD in Harness CI, you need to add a [DinD Background step](#add-a-dind-background-step) and a [Run step that runs Docker commands](#add-a-docker-run-step) to your [pipeline](#prepare-a-pipeline-for-dind).

### Kubernetes cluster build infrastructure required <a href="#kubernetes-cluster-build-infrastructure-required" id="kubernetes-cluster-build-infrastructure-required"></a>

Docker-in-Docker (DinD) with privileged mode is necessary only when using a [Kubernetes cluster build infrastructure](/continuous-integration/3.0/use-harness-ci/use-harness-ci/set-up-build-infrastructure/k8s-build-infrastructure.md). For other infrastructure types, you can run Docker commands directly on the host.

### Privileged mode required <a href="#privileged-mode-required" id="privileged-mode-required"></a>

Docker-in-Docker must run in privileged mode to work properly. Be aware that privileged mode provides full access to the host environment. For more information, go to the Docker documentation on [Runtime Privilege and Linux Capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).

You can't use DinD on platforms that don't support privileged mode, such as those that run containers on Windows.

### Prepare a pipeline for DinD <a href="#prepare-a-pipeline-for-dind" id="prepare-a-pipeline-for-dind"></a>

You need a [pipeline](/continuous-integration/3.0/use-harness-ci/use-harness-ci/prep-ci-pipeline-components.md) with a [Build stage](/continuous-integration/3.0/use-harness-ci/use-harness-ci/set-up-build-infrastructure/ci-stage-settings.md) that uses a [Kubernetes cluster build infrastructure](/continuous-integration/3.0/use-harness-ci/use-harness-ci/set-up-build-infrastructure/k8s-build-infrastructure.md). DinD is necessary for Kubernetes cluster build infrastructures only. For other infrastructure types, you can run Docker commands directly on the host.

To demonstrate how to set up DinD in Harness CI, this topic creates a pipeline that includes a DinD Background step and a Run step that builds and pushes an image. If you want to follow this example, you can configure your **Build** stage as follows:

1. In your pipeline, select the **Build** stage, and then select the **Overview** tab.
2. Under **Stage Details**, disable **Clone Codebase**. The example pipeline created in this topic doesn't use a [default codebase](/continuous-integration/3.0/use-harness-ci/use-harness-ci/codebase-configuration/create-and-configure-a-codebase.md); instead, the codebase is cloned by commands in the [Run step](#add-a-docker-run-step).
3. Under **Shared Paths**, add the following two paths:
   * `/var/run`
   * `/var/lib/docker`
4. Expand **Advanced**, and add [stage variables](/harness-platform/3.0/harness-platform-resources/overview/overview.md) for your Docker Hub Personal Access Token (PAT) and any other values that you want to parameterize.

   For passwords and Personal Access Tokens, select **Secret** as the variable type. For example, to add the Docker Hub PAT variable:

   * **Type:** Select **Secret**.
   * **Name:** Enter a name, such as `Docker Hub PAT`.
   * **Value:** Select a [Harness text secret](/harness-platform/3.0/harness-platform-resources/secrets/add-use-text-secrets.md) containing your Docker Hub PAT.
5. Select the **Infrastructure** tab.
6. Under **Infrastructure**, select **Kubernetes**, and then configure a [Kubernetes cluster build infrastructure](/continuous-integration/3.0/use-harness-ci/use-harness-ci/set-up-build-infrastructure/k8s-build-infrastructure.md).

### Add a DinD Background step <a href="#add-a-dind-background-step" id="add-a-dind-background-step"></a>

In your **Build** stage, select the **Execution** tab, and add a [Background step](/continuous-integration/3.0/use-harness-ci/use-harness-ci/manage-dependencies/background-step-settings.md) configured as follows:

1. For **Name**, enter `dind_Service`.
2. For **Container Registry**, select your [Docker connector](/harness-platform/3.0/harness-platform-resources/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md).
3. For **Image**, enter the name and tag for the image that you want to use to run DinD, such as [docker:dind](https://hub.docker.com/_/docker). In some cases, an FQN may be necessary. More information can be found below [about setting up the registry and image](#container-registry-and-image).
4. Under **Additional Configuration**, select **Privileged**. [Privileged mode is required](#privileged-mode-required) Docker-in-Docker to run correctly.
5. In **Entry Point**, you can provide a list of arguments, if needed. For example, the entry point for the `docker:dind` image is `docker-entrypoint.sh`. If you want to add a `--mtu` argument, you would include both the image entry point and the additional argument in the **Entry Point** specification.

{% tabs %}
{% tab title="Visual" %}

{% endtab %}

{% tab title="YAML" %}

```yaml
entrypoint:
  - docker-entrypoint.sh
  - "--mtu=1450"
```

{% endtab %}
{% endtabs %}

### Add a Docker Run step <a href="#add-a-docker-run-step" id="add-a-docker-run-step"></a>

After the **Background** step, add a **Run** step to run your Docker commands. Configure the [Run step settings](/continuous-integration/3.0/use-harness-ci/use-harness-ci/run-step-settings.md#run-step-settings) as follows:

1. Enter a **Name**.
2. For **Container Registry**, select your [Docker connector](/harness-platform/3.0/harness-platform-resources/connectors/cloud-providers/ref-cloud-providers/docker-registry-connector-settings-reference.md).
3. For **Image**, enter the name and tag for the Docker image, with the Docker binary, that you want to use to execute the content of **Command**. In some cases, an FQN may be necessary. More information can be found below [about setting up the registry and image](#container-registry-and-image).
4. In **Command**, enter the shell commands you want to run in this step.

   For example, the following commands clone a Git repo, build an image, and push the image to a Docker registry:

   ```
   apk add git
   git --version
   git clone https://github.com/$GITHUB_USERNAME/$GITHUB_REPO
   cd $GITHUB_REPO

   echo $DOCKERHUB_PAT > my_password.txt
   cat my_password.txt | docker login --username $DOCKERHUB_USERNAME --password-stdin

   docker build -t $DOCKER_IMAGE_LABEL
   docker tag $DOCKER_IMAGE_LABEL $DOCKERHUB_USERNAME/$DOCKER_IMAGE_LABEL:<+pipeline.sequenceId>
   docker push $DOCKERHUB_USERNAME/$DOCKER_IMAGE_LABEL:<+pipeline.sequenceId>
   ```

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>VARIABLES AND EXPRESSIONS</strong></p><p>The variables referenced in this command, such as <code>$DOCKERHUB_PAT</code>, refer to <a href="/harness-platform/3.0/harness-platform-resources/overview/overview.md">stage variables</a> that reference string values or <a href="/harness-platform/3.0/harness-platform-resources/secrets/add-use-text-secrets.md">Harness text secrets</a>.</p><p>These commands also use <code>&#x3C;+pipeline.sequenceId></code>, which is a <a href="/harness-platform/3.0/harness-platform-resources/variables-and-expressions/harness-variables.md">Harness expression</a> that prints the incremental build identifier.</p></div>

#### Wait for the container to initialize <a href="#wait-for-the-container-to-initialize" id="wait-for-the-container-to-initialize"></a>

When the build runs and the container starts, the software inside the container takes time to initialize and start accepting connections. Give the service adequate time to initialize before trying to connect. To do this, you can use a `while` loop in your **Command**, such as:

```
while ! docker ps ;do
      echo "Docker not available yet"
done
echo "Docker Service Ready"
docker ps
```

You can also add steps to your pipeline that [run health checks on background services](/continuous-integration/3.0/use-harness-ci/use-harness-ci/manage-dependencies/health-check-services.md).

### DinD and Docker container logs <a href="#dind-and-docker-container-logs" id="dind-and-docker-container-logs"></a>

When you run your pipeline, you can review the step logs on the [Build details page](/continuous-integration/3.0/use-harness-ci/use-harness-ci/viewing-builds.md).

#### Container Registry and Image <a href="#container-registry-and-image" id="container-registry-and-image"></a>

The build environment must have the necessary binaries for the **DinD** step. Depending on the stage's build infrastructure, **DinD** steps can use binaries that exist in the build environment, or use **Container Registry** and **Image** to pull an image, such as a public or private Docker image, that contains the required binaries.

### Pipeline YAML example <a href="#pipeline-yaml-example" id="pipeline-yaml-example"></a>

The following YAML example defines a pipeline that:

* Uses a [Kubernetes cluster build infrastructure](#kubernetes-cluster-build-infrastructure-required).
* Has a [Background step that runs DinD](#add-a-dind-background-step)
* Has a [Run step that runs a series of commands on a Docker image](#add-a-docker-run-step).

This example doesn't use a default codebase (`cloneCodebase: false`). Instead, the codebase is cloned by commands in the `Run` step.

```yaml
pipeline:
  name: dind-background-step-demo
  identifier: dindbackgroundstepdemo
  projectIdentifier: default
  orgIdentifier: default
  tags: {}
  stages:
    - stage:
        name: build
        identifier: build
        type: CI
        spec:
          cloneCodebase: false
          execution:
            steps:
              - step:
                  type: Background
                  name: Background
                  identifier: Background
                  spec:
                    connectorRef: YOUR_DOCKER_CONNECTOR_ID
                    image: docker:dind
                    shell: Sh
                    privileged: true
              - step:
                  type: Run
                  name: Run
                  identifier: Run
                  spec:
                    connectorRef: YOUR_DOCKER_CONNECTOR_ID
                    image: docker:run_step_image
                    shell: Sh
                    command: |-
                      while ! docker ps ;do
                            echo "Docker not available yet"
                      done
                      echo "Docker Service Ready"
                      docker ps

                      apk add git
                      git --version
                      git clone https://github.com/john-doe/$GITHUB_REPO
                      cd $GITHUB_REPO

                      echo $DOCKERHUB_PAT > my_password.txt
                      cat my_password.txt | docker login --username $DOCKERHUB_USERNAME --password-stdin

                      docker build -t $DOCKER_IMAGE_LABEL .
                      docker tag $DOCKER_IMAGE_LABEL $DOCKERHUB_USERNAME/$DOCKER_IMAGE_LABEL:<+pipeline.sequenceId>
                      docker push $DOCKERHUB_USERNAME/$DOCKER_IMAGE_LABEL:<+pipeline.sequenceId>
                    privileged: false
          infrastructure:
            type: KubernetesDirect
            spec:
              connectorRef: YOUR_K8S_CLUSTER_CONNECTOR_ID
              namespace: YOUR_K8S_NAMESPACE
              nodeSelector: {}
              os: Linux
          sharedPaths:
            - /var/run
            - /var/lib/docker
        variables:
          - name: DOCKERHUB_USERNAME
            type: String
            description: ""
            value: jdoe
          - name: DOCKERHUB_PAT
            type: Secret
            description: ""
            value: jdoedockerhubpat
          - name: GITHUB_USERNAME
            type: String
            description: ""
            value: j-doe
          - name: GITHUB_REPO
            type: String
            description: ""
            value: codebaseAlpha
          - name: GITHUB_PAT
            type: Secret
            description: ""
            value: jdoegithubpat
          - name: DOCKER_IMAGE_LABEL
            type: String
            description: ""
            value: dind-bg-step
```

### Troubleshoot Docker-in-Docker in Harness CI <a href="#troubleshoot-docker-in-docker-in-harness-ci" id="troubleshoot-docker-in-docker-in-harness-ci"></a>

Go to the [CI Knowledge Base](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md) for questions and issues related to script execution, using Run steps, and Docker-in-Docker, such as:

* [Does CI support running Docker-in-Docker images?](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md#does-ci-support-running-docker-in-docker-images)
* [Can't connect to Docker daemon with Docker-in-Docker Background step.](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md#cant-connect-to-docker-daemon)
* [Can I use an image that doesn't have a shell in a Run step?](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md#can-i-use-an-image-that-doesnt-have-a-shell-in-a-run-step)
* [What does the "Failed to get image entrypoint" error indicate in a Kubernetes cluster build?](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md#what-does-the-failed-to-get-image-entrypoint-error-indicate-in-a-kubernetes-cluster-build)
* [How do I start a service started in a container that would usually be started by the default entry point?](/continuous-integration/3.0/troubleshooting-and-resources/ci-articles-and-faqs/continuous-integration-faqs.md#since-the-default-entry-point-isnt-executed-for-the-container-image-used-in-the-run-step-how-do-i-start-a-service-started-in-a-container-that-would-usually-be-started-by-the-default-entry-point)

{% @harness-feedback/feedback %}
