Hallo alle! In seinem
Hauptseite
Alles begann an einem regnerischen Septemberabend, als ich die Maschine säuberte, die ich für 5 US-Dollar bei Digital Ocean gemietet hatte. Sie war eingefroren, weil Docker alle 24 Gigabyte verfügbaren Speicherplatz mit seinen Bildern und Containern gefüllt hatte. Die Ironie bestand darin, dass all diese Bilder und Container vorübergehend waren und nur dazu benötigt wurden, die Leistung meiner Anwendung jedes Mal zu testen, wenn eine neue Version einer Bibliothek oder eines Frameworks veröffentlicht wurde. Ich habe versucht, Shell-Skripte zu schreiben und einen Cron-Zeitplan einzurichten, um den Müll zu bereinigen, aber es hat nicht geholfen: Jedes Mal endete es unweigerlich damit, dass der Speicherplatz meines Servers aufgebraucht wurde und der Server (bestenfalls) hängen blieb. Irgendwann stieß ich auf einen Artikel darüber, wie man Jenkins in einem Container ausführt und wie es Build-Pipelines über einen dorthin weitergeleiteten Docker-Daemon-Socket erstellen und löschen kann. Die Idee gefiel mir, aber ich beschloss, noch einen Schritt weiter zu gehen und zu experimentieren, indem ich Docker direkt in Docker ausführte. Damals schien es mir eine völlig logische Lösung zu sein, Docker-Images herunterzuladen und Container für alle Anwendungen zu erstellen, die ich zum Testen in einem anderen Container (nennen wir es einen Staging-Container) benötigte. Die Idee bestand darin, einen Staging-Container mit dem Flag -rm zu starten, das beim Stoppen automatisch den gesamten Container und seinen gesamten Inhalt löscht. Ich habe am Docker-Image von Docker selbst herumgebastelt (
Üben. Kegel
Ich machte mich daran, den Behälter so zu gestalten, wie ich es brauchte, und setzte meine Experimente fort, was zu einer Vielzahl von Knospen führte. Das Ergebnis meiner Selbstquälerei war der folgende Algorithmus:
-
Wir starten den Docker-Container im interaktiven Modus.
docker run --privileged -it docker:18.09.6
Achten Sie auf die Version des Behälters, machen Sie einen Schritt nach rechts oder nach links und Ihr DinD verwandelt sich in einen Kürbis. Tatsächlich kommt es recht häufig zu Problemen, wenn eine neue Version veröffentlicht wird.
Wir müssen sofort in die Hülle eindringen. -
Wir versuchen herauszufinden, welche Container ausgeführt werden (Antwort: keine), aber führen wir den Befehl trotzdem aus:
docker ps
Sie werden ein wenig überrascht sein, aber es stellt sich heraus, dass der Docker-Daemon noch nicht einmal läuft:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such host
-
Lassen Sie es uns selbst ausführen:
dockerd &
Noch eine unangenehme Überraschung:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found
-
Installieren Sie die Pakete iptables und bash (alles ist in Bash angenehmer zu arbeiten als in SH):
apk add --no-cache iptables bash
-
Lasst uns Bash starten. Endlich sind wir wieder in der gewohnten Hülle
-
Versuchen wir, Docker erneut zu starten:
dockerd &
Wir sollten ein langes Protokollblatt sehen, das mit Folgendem 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
-
Drücken Sie Enter. Wir sind zurück in der Party.
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 starten möchten oder etwas schief geht und der Container abstürzt? Das ganze nochmal von vorne.
Eigener DinD-Container und neue Experimente
Um die oben genannten Schritte nicht immer wieder wiederholen zu müssen, habe ich meinen eigenen DinD-Container erstellt:
Die funktionierende DinD-Lösung gab mir die Möglichkeit, Docker innerhalb von Docker rekursiv auszuführen und abenteuerlichere Experimente durchzuführen.
Ich werde jetzt ein solches (erfolgreiches) Experiment mit der Ausführung von MySQL und Nodejs beschreiben.
Die Ungeduldigsten können hier sehen, wie es war
Also, fangen wir an:
-
Wir starten DinD im interaktiven Modus. In dieser Version von DinD 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 gelangen in die Bash, von wo aus wir sofort mit dem Starten untergeordneter Container beginnen können.
-
Starten Sie MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql
-
Wir stellen auf die gleiche Weise eine Verbindung zur Datenbank her, wie wir eine lokale Verbindung herstellen würden. Sorgen wir dafür, dass alles funktioniert.
-
Starten Sie den zweiten Container:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server
Bitte beachten Sie, dass die Portzuordnung exakt sein wird 8080:8080, da wir Port 80 vom Host zum übergeordneten Container bereits dem Port 8080 zugeordnet haben.
-
Wir gehen im Browser zu localhost und stellen sicher, dass der Server mit „Hello World!“ antwortet.
In meinem Fall verlief das Experiment mit verschachtelten Docker-Containern durchaus positiv und ich werde das Projekt weiterentwickeln und für das Staging nutzen. Mir scheint, dass dies eine viel einfachere Lösung ist als 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 Experimente mit der rekursiven Ausführung von Docker in Docker und dem Mounten von Verzeichnissen tief in verschachtelte Container ausführlicher beschreiben.
PS Wenn Sie dieses Projekt nützlich finden, geben Sie ihm bitte einen Stern auf GitHub, forken Sie es und erzählen Sie es Ihren Freunden.
Edit1 Fehler korrigiert, konzentriert auf 2 Videos
Source: habr.com