Docker tips & tricks - Running Docker in Docker

It is sometimes useful to be able to launch a container that can launch Docker tasks itself. This is done by installing Docker in a Docker container (Docker in Docker). It also involves mounting the host’s Linux sockets in the Container. Docker CLI itself uses the Docker socket to communicate with the Docker Engine.

This socket is located at this location:

ls -l /var/run/docker.sock

This command returns:

lrwxr-xr-x  1 root  daemon  63 10 nov 19:35 /var/run/docker.sock -> /Users/devops/Library/Containers/com.docker.docker/Data/docker.sock

Docker Engine is not actually executed inside the container: the Docker CLI is executed inside the container and communicates with the host to perform Docker tasks.

Let’s create a build script builder.sh:

rm docker-builder.sh
cat docker-builder.sh

The content of this file is:

#!/bin/sh
docker login -u $HUB_USERNAME -p $HUB_PASSWORD
docker build -t $1 .
docker push $1

Let’s give the execution rights to this script:

chmod +x ./docker-builder.sh

We want to deposit the Docker images created on Hub Docker. To do so, we introduce two environment variables for credentials ($HUB_USERNAME and $HUB_PASSWORD). The name of the image, including the repository, the name of the image and the tag are specified in the script parameter ($1).

This script can be improved by adding the execution of tests when running the container.

Let’s create a Dockerfile to build the Docker image of builder:

  • it is based on alpine,
  • it includes the buid script docker-builder.sh,
  • This script is run at each container launch with the docker run command.

Let’s create a Dockerfile with the following contents:

FROM alpine:latest
RUN apk update && \
    apk add docker
WORKDIR /app
COPY ./docker-builder.sh /usr/bin/docker-builder
ENTRYPOINT ["docker-builder"]
EOF

Let’s create this image, called docker-builder:

docker build -t docker-builder .

The output of the command is:

Sending build context to Docker daemon  4.608kB
Step 1/5 : FROM alpine:latest
latest: Pulling from library/alpine
Digest: sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a
Status: Downloaded newer image for alpine:latest
 ---> d6e46aa2470d
Step 2/5 : RUN apk update &&     apk add docker
 ---> Using cache
 ---> 259f11b4f190
Step 3/5 : WORKDIR /app
 ---> Using cache
 ---> 0d8f7dac7ed9
Step 4/5 : COPY ./docker-builder.sh /usr/bin/docker-builder
 ---> Using cache
 ---> 4cd2fcafd945
Step 5/5 : ENTRYPOINT ["docker-builder"]
 ---> Using cache
 ---> 11917e1ed916
Successfully built 11917e1ed916
Successfully tagged docker-builder:latest

Let’s define the environment variables for Hub Docker credentials:

HUB_USERNAME=<VOTRE NOM D'UTILISATEUR>
HUB_PASSWORD=<VOTRE MOT DE PASSE>

Let’s create a directory corresponding to the application:

mkdir -p app

Let’s create an app/Dockerfile that we want to build in the Docker container of the builder:

FROM alpine:latest

Now let’s run the docker-builder image which will itself run the docker build command in the app subdirectory to generate a new image based on the app/Dockerfile file.

First of all, let’s check that the image we are going to create is not present on the host:

docker images |grep docker-builder-test

This command does not return any result.

Now let’s run the build:

docker container run --rm \
    --name docker-builder \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v $PWD/app:/app \
    -e HUB_USERNAME=$HUB_USERNAME \
    -e HUB_PASSWORD=$HUB_PASSWORD \
    docker-builder devopstestlab/docker-builder-test:1.0

The result is:

WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM alpine:latest
 ---> d6e46aa2470d
Successfully built d6e46aa2470d
Successfully tagged devopstestlab/docker-builder-test:1.0
The push refers to repository [docker.io/devopstestlab/docker-builder-test]
ace0eda3e3be: Preparing
ace0eda3e3be: Layer already exists
1.0: digest: sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e size: 528

The Docker socket is mounted with the argument -v /var/run/docker.sock:/var/run/docker.sock.

Let’s check that the Docker image is now present on the host:

docker images |grep docker-builder-test

This time, we find this image locally:

devopstestlab/docker-builder-test   1.0                  d6e46aa2470d        2 weeks ago         5.57MB

By connecting to Hub Docker, you can find this image:

Hub Docker

Under Windows, instead of using the socket, you must use a pipe named using the argument -v \.\pipe\docker_engine:\.\pipe\docker_engine.

So we were able to generate a Docker image on the host from a Docker container dedicated to the build.

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×