Teracy's Blog

Get experience shared!

How to Use Docker in Docker (DinD) and Docker Outside of Docker (DooD) for Local CI Testing

Credit: https://github.com/jpetazzo/dind

Although running Docker inside Docker (DinD) or Docker outside of Docker (DooD) is generally not recommended, there are some legitimate use cases, such as development of Docker itself or for local CI testing. And in this blog post, I’m going to show you how to use DinD or DooD for local CI testing as it’s a very typical use case for local DevOps.

The differences between DinD and DooD?

DinD is the opposite of DooD.

DinD includes a whole Docker installation inside of it.

DooD uses its underlying host’s Docker installation by bind-mounting the Docker socket.

Obviously, DooD should be faster because we can leverage its caching mechanism, and DinD should be cleaner. DinD should support parallel running but DooD does not, or at least, not very reliable with my observation. If you want to conduct the clean testing, use DinD. If you want to conduct the faster testing, use DooD.

DooD is simpler to use than DinD.

And if you want to test with different versions of docker, docker-compose, use DinD and DooD.

Local CI testing with DinD

You can use https://hub.docker.com/r/library/docker/ for local testing, however, it’s alpine image which is not very suitable for local CI testing since it is not the default travis-ci environment. We should use Ubuntu for executing CI scripts on all the CI systems (gitlab, drone, etc.) because we can port the CI scripts easily between these CI systems.

That is the reason why we build teracy/ubuntu Docker images to be used with DinD, you can check out the project here: https://github.com/teracyhq/docker-files/tree/master/ubuntu and the built Docker images here: https://hub.docker.com/r/teracy/ubuntu/tags/

We also have docker-compose installed to the teracy/ubuntu Docker images for faster testing with it.

Let’s see how it works:

The commands from the above video:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ docker run --privileged --name df-docker -d docker:17.06.0-dind # start DinD container

$ docker run --rm -it --link df-docker:docker docker:17.06.0 sh # run docker image (Alpine)

# docker version

# docker-compose --version # no docker-compose

$ docker run --rm -it ubuntu bash # run Ubuntu image within the Docker Alpine container

# uname -a
# exit
# uname -a
# exit


$ docker run --rm -it --link df-docker:docker teracy/ubuntu:16.04-dind-17.06.0-ce bash # run Ubuntu image

# docker version
# docker-compose version

$ docker run --rm -it alpine sh # run Alpine image with the Docker Ubuntu container

# uname -a
# exit
# uname -a
# exit

Local CI testing with DooD

Let’s see how it works:

The commands from the above video:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker sh # start DooD container

# docker version
# docker-compose --version # no docker-compose

$ docker run --rm -it ubuntu bash # run Ubuntu image within the Docker Alpine container
# cat /etc/lsb-release
# exit
# cat /etc/alpine-release
# exit

$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock teracy/ubuntu:16.04-dind-17.06.0-ce bash # start DooD container

# docker version
# docker-compose version

# docker run --rm -it alpine sh # run Alpine image with the Docker Ubuntu container
# cat /etc/alpine-release
# exit
# cat /etc/lsb-release 
# exit

Volume mounting

Volume mounting is a bit tricky, you must understand the underlying mechanism of its to get it work. Basically, you need to make sure the mounting path from the running containers must be the same as the DinD containers or DooD containers.

Let’s see how volume mounting works with DinD:

The commands from the above video:

1
2
3
4
5
6
7
8
9
# volume mount with DinD

$ pwd
$ ls
$ docker run --privileged --name df-docker -d -v $(pwd):$(pwd) -w $(pwd) docker:17.06.0-dind # start DinD container
$ docker run --rm -it --link df-docker:docker -v $(pwd):$(pwd) -w $(pwd) teracy/ubuntu:16.04-dind-17.06.0-ce bash
# ls
# docker run --rm -it -v $(pwd):/opt/app -w /opt/app ubuntu bash
# ls

Let’s see how volume mounting works with DooD:

The commands from the above video:

1
2
3
4
5
6
7
# volume mount with DooD
$ pwd
$ ls
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd):/$(pwd) -w $(pwd) teracy/ubuntu:16.04-dind-17.06.0-ce bash # start DooD container
# ls
# docker run --rm -it -v $(pwd):/opt/app -w /opt/app ubuntu bash
# ls

Local CI Testing with a real project

Let’s see how we can conduct a local CI testing with the https://github.com/teracyhq/docker-files project.

Let’s dive into the .travis.yml file https://github.com/teracyhq/docker-files/blob/master/.travis.yml to test the following scripts:

1
2
3
4
5
6
7
8
9
10
11
12
before_install:
# install the latest docker and docker-compose versions
- sudo apt-get remove docker docker-engine
- sudo curl -sSL https://get.docker.com/ | sh
- sudo rm /usr/local/bin/docker-compose
# the latest docker-compose version
- export DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4)
- curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
- chmod +x docker-compose
- sudo mv docker-compose /usr/local/bin
- docker version
- docker-compose version

Let’s see how to do local CI testing in action:

This is just the very first step for basic testing.

Later, we should convert this .travis.yml file into a build.sh one to execute, this is the right way for local CI testing travis-ci and other similar CI systems.

To do that, please follow https://github.com/teracyhq/docker-files/issues/42 and I’ll update this section more when it’s ready.

Too many virtualization layers?

At Teracy, the teracy-dev VM is virtualized on a host machine (and the host machine could be virtualized from another virtualized machine and so on).

Within the teracy-dev VM, we use DinD. And within a Docker container, we can use Docker to run other Docker containers and so on.

Yeah, welcome to the world of “Inception”, let’s figure out where you are now :–)?

Happy hacking!

References

Comments