Wie ich Docker in Docker gestartet habe und was dabei herausgekommen ist

Hallo allerseits! In meinem vorherigen Artikel habe ich versprochen, über den Start von Docker in Docker und die praktischen Aspekte der Anwendung dieser Lektion zu sprechen. Es ist Zeit, unser Versprechen zu halten. Ein erfahrener Devo würde vielleicht argumentieren, dass diejenigen, die Docker in Docker benötigen, einfach den Docker-Dämonen-Sockel vom Host in den Container werfen und dies ist in 99% der Fälle ausreichend. Aber beeilen Sie sich nicht, mir Kekse zuzuwerfen, denn wir werden über den tatsächlichen Start von Docker in Docker sprechen. Diese Lösung hat viele mögliche Anwendungsbereiche. In diesem Artikel geht es um eines davon. Lehnen Sie sich zurück und strecken Sie die Arme vor sich.


Bild

Starten Sie


Alles begann an einem verregneten Septemberabend, als ich einen Mietwagen von Digital Ocean für 5 US-Dollar aufräumte. Dieser hing eng zusammen, weil Docker alle 24 Gigabyte des verfügbaren Speicherplatzes mit seinen Bildern und Containern füllte. Die Ironie bestand darin, dass all diese Bilder und Container vorübergehend waren und nur zum Testen der Leistung meiner Anwendung bei jedem Erscheinen einer neuen Version einer Bibliothek oder eines Frameworks benötigt wurden. Ich habe versucht, Shell-Skripte zu schreiben und den Zeitplan für die Müllbereinigung zu konfigurieren, aber das hat nicht gespart: Jedes Mal, wenn sich herausstellte, dass der Festplattenspeicher meines Servers aufgebraucht war, hing der Server (bestenfalls). Irgendwann stieß ich auf einen Artikel über das Ausführen von Jenkins in einem Container und das Erstellen und Löschen von Assembly-Pipelines über den Docker-Daemon-Socket. Die Idee hat mir gefallen, aber ich habe mich entschlossen, mit dem direkten Start von Docker in Docker zu experimentieren. Es schien mir damals eine völlig logische Entscheidung zu sein, Docker-Images auszupumpen und Container mit allen Anwendungen zu erstellen, die ich zum Testen in einem anderen Container benötige (nennen wir es einen Staging-Container). Die Idee war, einen Staging-Container mit dem Flag -rm auszuführen, der beim Anhalten automatisch den gesamten Container mit seinem gesamten Inhalt löscht. Ich habe mit dem Docker-Image vom Docker selbst gestöbert ( https://hub.docker.com/_/docker ), aber es stellte sich als zu umfangreich heraus und ich konnte es nicht zum gewünschten Zweck zum Laufen bringen.


Übe. Beulen


Ich machte mich daran, den Container nach Bedarf zum Laufen zu bringen, und setzte meine Experimente fort, die zu einer Vielzahl von Zapfen führten. Das Ergebnis meiner Selbstquälerei war der folgende Algorithmus:


  1. Wir starten den Docker-Container in einem interaktiven Modus.


    docker run --privileged -it docker:18.09.6 

    Achten Sie auf die Version des Behälters, einen Schritt nach rechts oder links und Ihr DinD verwandelt sich in einen Kürbis. Tatsächlich bricht mit der Veröffentlichung einer neuen Version ziemlich oft alles zusammen.
    Wir müssen sofort in die Schale kommen.


  2. Versuchen Sie herauszufinden, welche Container ausgeführt werden (Antwort: keine), aber führen Sie den Befehl trotzdem aus:


     docker ps 

    Sie werden ein wenig überrascht sein, aber es stellt sich heraus, dass der Docker-Dämon nicht einmal ausgeführt wird:


     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. Lass es uns selbst machen:


     dockerd & 

    Eine weitere unangenehme Überraschung:


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

  4. Installieren Sie die Pakete iptables und bash (die Arbeit mit bash ist angenehmer als mit sh):


     apk add --no-cache iptables bash 

  5. Wir fangen an zu prügeln. Endlich sind wir wieder in der gewohnten Schale


  6. versuchen Sie Docker erneut zu starten:


     dockerd & 

    Wir sollten ein langes Protokoll sehen, das endet:


     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. Drücken Sie die Eingabetaste. Wir sind zurück in der Bash.



Von nun an können wir versuchen, andere Container in unserem Docker-Container zu starten, aber was ist, wenn wir einen anderen Docker-Container in unserem Docker-Container anheben möchten oder etwas schief geht und der Container "herausfliegt"? Fangen Sie noch einmal von vorne an.


Eigener DinD-Container und neue Experimente



Um die obigen Schritte nicht immer wieder zu wiederholen, habe ich einen eigenen DinD-Container angelegt:


https://github.com/alekslitvinenk/dind


Die funktionierende DinD-Lösung gab mir die Möglichkeit, Docker rekursiv in Docker auszuführen und mutigere Experimente durchzuführen.
Ein solches (erfolgreiches) Experiment mit MySQL und Nodejs werde ich jetzt beschreiben.
Die ungeduldigsten können sehen, wie es hier war



Also fangen wir an:


  1. Starten Sie DinD interaktiv. In dieser DinD-Version müssen wir alle Ports, die unsere untergeordneten Container verwenden können, manuell zuordnen (daran arbeite ich bereits).


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

    Wir befinden uns in einer Bash, von wo aus wir sofort anfangen können, Hilfscontainer auf den Markt zu bringen.


  2. Wir starten MySQL:


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

  3. Wir stellen die Verbindung zur Datenbank auf dieselbe Weise her, wie wir sie lokal herstellen würden. Stellen Sie sicher, dass alles funktioniert.


  4. Wir starten den zweiten Container:


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

    Beachten Sie, dass die Portzuordnung hier genau 8080: 8080 lautet , da wir bereits Port 80 vom Host auf den übergeordneten Container auf Port 8080 abgebildet haben.


  5. Wir gehen im Browser zu localhost und sind überzeugt, dass der Server "Hello World!" Antwortet.



In meinem Fall war das Experiment mit den beigefügten Docker-Containern recht positiv, und ich werde das Projekt weiterentwickeln und für die Inszenierung verwenden. Es scheint mir, dass dies eine viel leichtere Lösung ist als die gleichen Kubernetes und Jenkins X. Aber das ist meine subjektive Meinung.


Ich denke, das ist alles für den heutigen Artikel. Im nächsten Artikel werde ich detailliertere Experimente mit dem rekursiven Start von Docker in Docker und dem Mounten von Verzeichnissen in verschachtelten Containern beschreiben.


PS Wenn Sie dieses Projekt nützlich finden, geben Sie es bitte auf dem GitHub mit einem Sternchen an, geben Sie es heraus und teilen Sie es Ihren Freunden mit.


Edit1 Behobene Fehler, die sich auf 2 Videos konzentrierten

Source: https://habr.com/ru/post/de477464/


All Articles