DinD - Docker Inside Docker
One of the (many!) features of Docker 0.6 is the new “privileged” mode for containers. It allows you to run some containers with (almost) all the capabilities of their host machine, regarding kernel features and device access.
Among the (many!) possibilities of the “privileged” mode, you can now run Docker within Docker itself. First, we will see how to make that happen; next, we will explain what is involved under the hood, and finally, we will show something even more powerful than Docker in Docker!
See Docker-in-Docker in action
If you have Docker 0.6, all you have to do is:
docker run -privileged -t -i jpetazzo/dind
This will download a special Docker image (we will see later why it is special), and execute it in the new privileged mode. By default, it will run a local docker
daemon, and drop you into a shell. In that shell, let’s try a classical “Docker 101” command:
docker run -t -i ubuntu bash
Note how the container ID changes as you transition from the container running Docker, to the innermost container!
What’s special in this dind
image?
Almost nothing! It is built with a regular Dockerfile. Let’s see what is in that Dockerfile.
First, it installs a few packages: lxc
and iptables
(because Docker needs them), and ca-certificates
(because when communicating with the Docker index and registry, Docker needs to validate their SSL certificates).
The Dockerfile also indicates that /var/lib/docker
should be a volume. This is important, because the filesystem of a container is an AUFS mountpoint, composed of multiple branches; and those branches have to be “normal” filesystems (i.e. not AUFS mountpoints). In other words, /var/lib/docker
, the place where Docker stores its containers, cannot be an AUFS filesystem. Therefore, we instruct Docker that this path should be a volume. Volumes have many purposes, but in this scenario, we use them as a pass-through to the “normal” filesystem of the host machine. The /var/lib/docker
directory of the nested Docker will live somewhere in /var/lib/docker/volumes
on the host system.
And of course, the Dockerfile injects the Docker binary in the image, as well as a helper script. The helper script deals with three things.
- It ensures that the cgroup pseudo-filesystems are properly mounted, because Docker (or, more accurately,
lxc-start
) needs them. - It closes extraneous file descriptors which might have been leaked from the parent process. This is not strictly necessary, but you might notice weird side effects if you don’t do it; so I took care of it for you.
- It checks if you specified a
PORT
environment variable through the-e PORT=...
command-line option. If you did, the Docker daemon starts in the foreground, and listens for API requests on the specified TCP port. If you did not specify aPORT
variable, it will start Docker in the background, and give you an interactive shell.
source: Jérôme Petazzoni