How I launched Docker inside Docker and what came of it

Hello! In my previous article , I promised to talk about the launch of Docker in Docker and the practical aspects of applying this lesson. It is time to keep our promise. An experienced devo, perhaps, would argue that those who need Docker inside Docker simply forward the Docker demon socket from the host inside the container and this is enough in 99% of cases. But do not rush to throw cookies at me, because we will talk about the real launch of Docker inside Docker. This solution has many possible fields of application and this article is about one of them, so sit back and straighten your arms in front of you.











image






Start



It all started on a rainy September evening when I was cleaning a Digital Ocean rental car for $ 5, which hung tight because Docker filled all 24 gigabytes of available disk space with its images and containers. The irony was that all these images and containers were transient and needed only to test the performance of my application every time a new version of a library or framework was released. I tried to write shell-scripts and adjust the crowns schedule for garbage cleaning, but this did not save: every time everything inevitably ended up with the disk space of my server being eaten up and the server freezing (at best). At some point, I came across an article about how to run Jenkins in a container and how it can create and delete assembly pipelines through the docker daemon socket thrown into it. I liked the idea, but I decided to go ahead and try to experiment with the direct launch of Docker inside Docker. It seemed to me then a completely logical decision to pump out docker images and create containers of all the applications that I need for testing inside another container (let's call it a staging container). The idea was to run a staging container with the -rm flag, which automatically deletes the entire container with all its contents when it stops. I rummaged with the docker image from the Docker itself ( https://hub.docker.com/_/docker ), but it turned out to be too bulky and I was not able to get it to work as I needed and I wanted to go all the way myself.







Practice. Bumps



I set out to make the container work as I needed and continued my experiments, which resulted in a myriad of cones. The result of my self-torture was the following algorithm:







  1. We launch the Docker container in an interactive mode.







    docker run --privileged -it docker:18.09.6
          
          





    Pay attention to the version of the container, a step to the right or to the left and your DinD turns into a pumpkin. In fact, everything breaks down quite often with the release of a new version.

    We must immediately get into the shell.







  2. We try to find out which containers are running (Answer: none), but let's execute the command anyway:







     docker ps
          
          





    You will be a little surprised, but it turns out the Docker daemon is not even running:







     error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such host
          
          





  3. Let's run it yourself:







     dockerd &
          
          





    Another unpleasant surprise:







     failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found
          
          





  4. Install the iptables and bash packages (itโ€™s more pleasant to work in the bash than in sh):







     apk add --no-cache iptables bash
          
          





  5. We start bash. Finally we are back in the usual shell







  6. try to launch docker again:







     dockerd &
          
          





    We should see a long sheet of logs ending:







     INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock
          
          





  7. Press Enter. We are back in the bash.









From now on, we can try to launch other containers inside our Docker container, but what if we want to raise another Docker container inside our Docker container or something goes wrong and the container will โ€œfly outโ€? Start all over again.







Own DinD container and new experiments









In order not to repeat the above steps again and again, I created my own DinD container:







https://github.com/alekslitvinenk/dind







The working DinD solution gave me the opportunity to run Docker inside Docker recursively and conduct bolder experiments.

One such (successful) experiment with starting MySQL and Nodejs, Iโ€™m going to describe now.

The most impatient can see how it was here









So, let's begin:







  1. Launch DinD interactively. In this version of DinD, we need to manually map all the ports that our child containers can use (I'm already working on this)







     docker run --privileged -it \ -p 80:8080 \ -p 3306:3306 \ alekslitvinenk/dind
          
          





    We find ourselves in a bash, from where we can immediately begin to launch subsidiary containers.







  2. We start MySQL:







     docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql
          
          





  3. We connect to the database in the same way as we would connect to it locally. Make sure everything works.







  4. We launch the second container:







     docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server
          
          





    Please note that the port mapping here will be exactly 8080: 8080 , since we have already mapped port 80 from the host to the parent container on port 8080.







  5. We go to localhost in the browser, we are convinced that the server answers "Hello World!".









In my case, the experiment with the docker containers enclosed was quite positive, and I will continue to develop the project and use it for staging. It seems to me that this is a much more lightweight solution than the same Kubernetes and Jenkins X. But this is my subjective opinion.







I think that for today's article is all. In the next article, I will describe in more detail experiments with the recursive launch of Docker in Docker and mounting directories deep into nested containers.







PS If you find this project useful, then please give it an asterisk on the GitHub, fork and tell your friends.







Edit1 Corrected errors, made focus on 2 videos








All Articles