Jak uruchomiłem Dockera w Dockerze i co z tego wyszło

Cześć wszystkim! W jego Poprzedni artykuł, obiecałem porozmawiać o uruchamianiu Dockera w Dockerze i praktycznych aspektach korzystania z tej lekcji. Czas dotrzymać obietnicy. Doświadczony devopser prawdopodobnie zaprotestuje, twierdząc, że ci, którzy potrzebują Dockera w Dockerze, po prostu przekażą gniazdo demona Docker z hosta do kontenera i to wystarczy w 99% przypadków. Ale nie spiesz się z rzucaniem we mnie ciasteczkami, ponieważ porozmawiamy o faktycznym uruchomieniu Dockera w Dockerze. To rozwiązanie ma wiele możliwych zastosowań i ten artykuł dotyczy jednego z nich, dlatego usiądź wygodnie i wyprostuj ramiona przed sobą.

Jak uruchomiłem Dockera w Dockerze i co z tego wyszło

początek

Wszystko zaczęło się pewnego deszczowego wrześniowego wieczoru, kiedy czyściłem maszynę wypożyczoną za 5 dolarów w Digital Ocean, która została zamrożona, ponieważ Docker zapełnił swoimi obrazami i kontenerami wszystkie 24 gigabajty dostępnego miejsca na dysku. Ironią losu było to, że wszystkie te obrazy i kontenery były tymczasowe i potrzebne tylko do testowania wydajności mojej aplikacji za każdym razem, gdy wydawana była nowa wersja biblioteki lub frameworka. Próbowałem pisać skrypty powłoki i konfigurować harmonogram cron do czyszczenia śmieci, ale to nie pomogło: za każdym razem kończyło się to nieuchronnie zajęciem miejsca na dysku mojego serwera i zawieszaniem się serwera (w najlepszym wypadku). W pewnym momencie natknąłem się na artykuł o tym, jak uruchomić Jenkinsa w kontenerze oraz jak może on tworzyć i usuwać potoki kompilacji za pośrednictwem przekazanego do niego gniazda demona dokującego. Podobał mi się ten pomysł, ale zdecydowałem się pójść dalej i spróbować poeksperymentować z bezpośrednim uruchamianiem Dockera w Dockerze. W tamtym czasie całkowicie logicznym rozwiązaniem wydawało mi się pobieranie obrazów Dockera i tworzenie kontenerów dla wszystkich aplikacji, które potrzebowałem do testowania w innym kontenerze (nazwijmy to kontenerem pomostowym). Pomysł polegał na uruchomieniu kontenera pomostowego z flagą -rm, która po zatrzymaniu automatycznie usuwa cały kontener i całą jego zawartość. Majstrowałem przy obrazie Dockera z samego Dockera (https://hub.docker.com/_/docker), ale okazało się to zbyt kłopotliwe i nigdy nie udało mi się sprawić, żeby działało tak, jak tego potrzebowałem, a chciałem przejść całą drogę sam.

Ćwiczyć. Szyszki

Postanowiłem sprawić, że pojemnik będzie działał tak, jak potrzebowałem, i kontynuowałem eksperymenty, które zaowocowały niezliczoną ilością pąków. Efektem moich samotortur był następujący algorytm:

  1. Uruchamiamy kontener Docker w trybie interaktywnym.

    docker run --privileged -it docker:18.09.6

    Zwróć uwagę na wersję pojemnika, wykonaj krok w prawo lub w lewo, a Twój DinD zamieni się w dynię. W rzeczywistości rzeczy często się psują, gdy wydawana jest nowa wersja.
    Musimy natychmiast dostać się do skorupy.

  2. Próbujemy dowiedzieć się, które kontenery są uruchomione (odpowiedź: żaden), ale mimo to uruchommy polecenie:

    docker ps

    Będziesz trochę zaskoczony, ale okaże się, że demon Dockera nawet nie działa:

    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. Uruchommy to sami:

    dockerd &

    Kolejna nieprzyjemna niespodzianka:

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

  4. Zainstaluj pakiety iptables i bash (w bash wszystko jest przyjemniejsze niż w sh):

    apk add --no-cache iptables bash

  5. Uruchommy basha. Wreszcie wracamy do zwykłej powłoki

  6. Spróbujmy ponownie uruchomić Dockera:

    dockerd &

    Powinniśmy zobaczyć długi arkusz dzienników kończący się słowami:

    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. Naciśnij enter. Wracamy do bash'a.

Od tej chwili możemy próbować uruchamiać inne kontenery w naszym kontenerze Docker, ale co jeśli będziemy chcieli uruchomić kolejny kontener Docker w naszym kontenerze Docker lub coś pójdzie nie tak i kontener ulegnie awarii? Zacznij od początku.

Własny kontener DinD i nowe eksperymenty

Jak uruchomiłem Dockera w Dockerze i co z tego wyszło
Aby uniknąć ciągłego powtarzania powyższych kroków, stworzyłem własny kontener DinD:

https://github.com/alekslitvinenk/dind

Działające rozwiązanie DinD umożliwiło mi rekursywne uruchamianie Dockera w Dockerze i przeprowadzanie bardziej ryzykownych eksperymentów.
Opiszę teraz jeden z takich (udanych) eksperymentów z uruchomieniem MySQL i Nodejs.
Najbardziej niecierpliwi mogą zobaczyć jak było tutaj

Zacznijmy:

  1. Uruchamiamy DinD w trybie interaktywnym. W tej wersji DinD musimy ręcznie zmapować wszystkie porty, z których mogą korzystać nasze kontenery podrzędne (już nad tym pracuję)

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

    Przechodzimy do basha, skąd możemy od razu przystąpić do uruchamiania kontenerów podrzędnych.

  2. Uruchom MySQL'a:

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

  3. Z bazą danych łączymy się w taki sam sposób, jak łączylibyśmy się z nią lokalnie. Upewnijmy się, że wszystko działa.

  4. Uruchom drugi kontener:

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

    Należy pamiętać, że mapowanie portów będzie dokładne 8080:8080, ponieważ zmapowaliśmy już port 80 z hosta do kontenera nadrzędnego na port 8080.

  5. Wchodzimy do localhost w przeglądarce, upewniamy się, że serwer odpowiada „Hello World!”

W moim przypadku eksperyment z zagnieżdżonymi kontenerami Dockera wypadł całkiem pozytywnie i będę dalej rozwijać projekt i wykorzystywać go do stagingu. Wydaje mi się, że jest to dużo lżejsze rozwiązanie niż Kubernetes i Jenkins X. Ale to jest moja subiektywna opinia.

Myślę, że to wszystko w dzisiejszym artykule. W następnym artykule opiszę bardziej szczegółowo eksperymenty z rekurencyjnym uruchamianiem Dockera w Dockerze i montowaniem katalogów głęboko w zagnieżdżonych kontenerach.

PS Jeśli uznasz ten projekt za przydatny, daj mu gwiazdkę na GitHubie, rozwidl go i powiedz znajomym.

Edit1 Poprawione błędy, skupiono się na 2 filmach

Źródło: www.habr.com

Dodaj komentarz