Skip to Sidebar Skip to Content

3 Best Ways to Run Docker in Docker Container

3 Best Ways to Run Docker in Docker Container

Highlights

  • Method Variations: Learn the top three methods to Run Docker in Docker: mounting the Docker socket, using the docker:dind image, or leveraging the Nestybox Sysbox runtime.
  • Pipeline Automation: Discover how a proper CI/CD Docker setup can streamline building and pushing images directly from your runner containers.
  • Security Considerations: Understand the security trade-offs of privileged mode versus socket mounting when configuring Nested Docker containers.
  • Environment Isolation: Learn how a Docker in Docker setup provides an excellent sandbox for testing complex builds without cluttering the host system.
  • Runtime Alternatives: Explore modern solutions like Sysbox that avoid the risks associated with traditional privileged containers.

Docker is a popular tool for building, running, and managing containers. But what if you want to Run Docker in Docker, for instance, in a CI pipeline? How can you achieve that?

In this DinD tutorial, I will demonstrate three different methods for running a Docker inside container environment and explain the pros and cons of each. I will also share some use cases and tips for using Docker effectively.

Key Takeaways

  • Mounting the host’s Docker socket is simple and does not require any special privileges or configuration, but it gives the container full access to the host’s Docker daemon, which can be a security risk.
  • Using the docker:dind image creates a separate namespace for the inner Docker daemon and its containers, which avoids interference with the host’s daemon or other containers, but it requires privileged mode, which gives the container complete access to the host system.
  • Using Nestybox Sysbox runtime enables containers to act as lightweight VMs that can run system-level software such as Docker without requiring privileged mode or special configuration.

Why Run Docker in Docker?

Below are some of the scenarios where you might want to establish a Docker in Docker setup:

  • CI/CD pipelines: If you use a containerized CI/CD system, such as Jenkins, GitLab CI, or GitHub Actions, you might need to build and push Docker images as part of your pipeline stages. Using a CI/CD Docker setup allows you to do that without installing Docker on your CI/CD agents or using a separate VM.
  • Sandboxed environments: If you want to experiment with advanced Docker CLI commands or test your Dockerfiles without affecting your host system, you can use a Docker inside container sandbox. This way, you can isolate your experiments from your production environment and avoid potential conflicts or errors.
  • Portability: Nested Docker containers can be easily shared and distributed because they package up the Docker engine and environment. This makes the Dockerized app portable and self-contained.
  • Learning and teaching: If you are learning or teaching about Docker, you can use a Docker in Docker container as a playground to practice and demonstrate various concepts and features of Docker. You can also use it to run multiple containers on a single machine without consuming too much resources.

Try the Docker Run Lab for free:

Docker Run Lab
Docker Run Lab

Let us now look at the three methods of running Docker inside a Docker container.

1: Mounting the Host’s Docker Socket

This method to Run Docker in Docker involves mounting the host's Docker socket (/var/run/docker.sock) into the container. This way, the Docker CLI inside the container can communicate with the host's Docker daemon and execute commands on it.

To use this method, you need to run a container with the -v /var/run/docker.sock:/var/run/docker.sock option. See the command below:

docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker:18.06

This command will run a container using the official docker image from Docker Hub, which has the Docker CLI installed. You can also use any other image that has the docker binary or install it yourself. You can now log into the container using this command:

docker exec -it <CONTAINER_ID> /bin/sh

Once inside the container, you can run any docker command. Let’s start an Nginx container using the command below:

docker container run -d --name=sock-nginx nginx

Then run this command to verify the container has been created:

docker ps

Running the command above gives an output similar to this:

Check the version of the docker binary installed in your container:

docker --version

You should see something like this:

This method is advantageous because it is simple and does not require special privileges or configuration. However, it gives the container full access to the host’s Docker daemon, which can be a security risk. Also, any containers created by the inner Docker will reside on the host system alongside the outer container, which can cause confusion or conflicts.

2: Using the docker:dind Image

The second method to run Docker in Docker is to use the docker:dind image, which stands for “Docker in Docker”. This image provides a self-contained Docker daemon installation inside the container. It operates independently of the host’s daemon, so docker ps inside the container will give different results than docker ps on the host.

To use this method, you need to run a container with the --privileged option and some additional flags. For example:

docker run --privileged --name docker -e DOCKER_TLS_CERTDIR=/certs -v docker-certs-ca:/certs/ca -v docker-certs-client:/certs/client docker:dind

This command will run a container using the docker:dind image and set up some environment variables and volumes for TLS authentication. You can also use other options, such as -p to expose ports or -d to run in detached mode.

Log into the container using this command:

docker exec -it docker /bin/sh

Once inside the container, you can run any docker command as usual:

docker container run -d --name=mynginx nginx

Then run this command to verify the container is up and running:

docker ps

You will see something like this:

To check the version of the docker binary that is installed, run the following command in the container:

docker --version

You will see something like this:

This method has the advantage of creating a separate namespace for the inner Docker daemon and its containers, which avoids interfering with the host’s daemon or other containers.

However, it requires privileged mode, which gives the container complete access to the host system. This can be an unacceptable security risk in some environments. Also, there are some issues with Linux Security Modules (LSM), such as AppArmor and SELinux, and with storage drivers that can cause problems with this method.

3: Using Nestybox Sysbox Runtime

The third method to run Docker in a Docker container is to use the Nestybox Sysbox runtime, which is a container runtime that enables containers to act as lightweight VMs. This means that containers can run system-level software such as Docker, Kubernetes, systemd, etc., without requiring privileged mode or special configuration.

To use this method, you need to install the Nestybox Sysbox runtime on your host system and then run a container with the --runtime=sysbox-runc option. For example:

docker run --runtime=sysbox-runc --name sysbox-docker -d docker:dind

The command above starts a docker:dind container with a sysbox runtime. After the container is started, log into the container using this command:

docker exec -it sysbox-docker /bin/sh

Once inside the container, you can run Docker commands on its shell. You can test if the container is working as expected by running the following command:

docker container run -d --name=sysbox-nginx nginx

Then run the following command:

docker ps

You should see an output similar to this:

This method provides a secure and robust way to run a Docker inside container architecture without requiring privileged mode or special configuration.

The disadvantage is that it requires installing and configuring a new runtime on your host system.

PRACTICE the concepts discussed here in a real-world live environment for FREE with KodeKloud Engineer. Join thousands of students gaining real, hands-on experience by working on actual project tasks on a live system.

Best Practices for Docker in Docker

Here are some best practices for managing your Docker in Docker setup effectively:

  • Choose the right method for your use case. Depending on your needs and priorities, you may prefer mounting the host’s Docker socket, using the docker:dind image, using Nestybox Sysbox runtime, or using Podman. Each method has its own advantages and disadvantages, so weigh them carefully before deciding.
  • Keep your images small and secure. To reduce their size and vulnerability, use multistage builds, minimal base images, trusted sources, and image scanning tools. Avoid using privileged mode or exposing the Docker daemon socket unless absolutely necessary. Use rootless containers or non-root users whenever possible.
  • Tag your images with useful information. Use descriptive and consistent tags that codify version information, intended destination, stability, or other relevant metadata. Do not rely on the automatically created latest tag, as it may not reflect the actual state of your image. Instead, use semantic versioning or other conventions to manage your image versions.
  • Follow the general guidelines and recommendations for writing Dockerfiles. Use .dockerignore files to exclude unnecessary files from your build context. Use ENV to define environment variables. Use COPY instead of ADD unless you need to extract a tar file or fetch a remote URL. Use WORKDIR instead of RUN cd. Use ENTRYPOINT and CMD to specify what command to run within the container.

To learn Docker concepts, such as networking and container orchestration, with hands-on labs, check out our Docker Learning Path.

Docker Learning Path | Kodekloud

Conclusion

In this article, I have shown you three different methods to Run Docker in Docker and explained the pros and cons of each one. I have also provided some use cases and tips for using Docker effectively. You should choose the method that suits your needs and security requirements.


More on Docker:


FAQs

Q1: What is the easiest way to achieve a CI/CD Docker setup?

Mounting the host's docker.sock is often the easiest path for CI/CD runners, as it avoids privileged mode while allowing the runner to build images using the host's daemon. However, use this strictly in trusted CI environments due to security risks.

Q2: Does the docker:dind image require special flags?

Yes, starting a traditional DinD tutorial image requires passing the --privileged flag to the docker run command so the nested daemon has the required system capabilities.

Q3: What are the security risks of Nested Docker containers?

Using the --privileged flag gives the container almost complete access to the host system's resources and devices, making it a major security risk if compromised.

Q4: Can I run Kubernetes inside a Docker inside container setup?

Yes, tools like kind (Kubernetes in Docker) utilize similar DinD concepts to spin up local Kubernetes clusters completely inside Docker containers for testing and development.

Q5: How does Sysbox improve the Docker in Docker setup?

Sysbox acts as a dedicated runtime that securely isolates containers while still allowing them to run system-level software (like Docker or systemd) without needing the dangerous --privileged flag.

Barry Ugochukwu Barry Ugochukwu
Barry is a machine learning expert with software engineering skills. He uses Kubernetes and DevOps tools to deliver and manage software solutions. He offers reliable and useful insights to readers.

Subscribe to Newsletter

Join me on this exciting journey as we explore the boundless world of web design together.