Ako som spustil Docker v Dockeri a čo z toho vyšlo

Ahojte všetci! V jeho predchádzajúci článok, sľúbil som, že sa porozprávam o spustení Dockera v Dockeri a praktických aspektoch používania tejto lekcie. Je čas dodržať svoj sľub. Skúsený devopser pravdepodobne namietne, že tí, ktorí potrebujú Docker v Dockeri, jednoducho preposielajú zásuvku démona Docker z hostiteľa do kontajnera a to bude v 99% prípadov stačiť. Ale neponáhľajte sa na mňa hádzať cookies, pretože budeme hovoriť o skutočnom spustení Dockeru v Dockeri. Toto riešenie má mnoho možných aplikácií a tento článok je o jednej z nich, takže sa pohodlne usaďte a narovnajte ruky pred sebou.

Ako som spustil Docker v Dockeri a čo z toho vyšlo

začiatok

Všetko to začalo v daždivý septembrový večer, keď som čistil stroj, ktorý som si prenajal za 5 dolárov na Digital Ocean, ktorý bol zmrazený kvôli skutočnosti, že Docker zaplnil všetkých 24 gigabajtov dostupného miesta na disku svojimi obrázkami a kontajnermi. Iróniou bolo, že všetky tieto obrázky a kontajnery boli prechodné a boli potrebné len na testovanie výkonu mojej aplikácie zakaždým, keď bola vydaná nová verzia knižnice alebo rámca. Pokúsil som sa písať skripty shellu a nastaviť plán cron na vyčistenie odpadu, ale nepomohlo to: zakaždým to nevyhnutne skončilo tým, že miesto na disku môjho servera bolo spotrebované a server visel (v najlepšom prípade). V určitom momente som narazil na článok o tom, ako spustiť Jenkins v kontajneri a ako môže vytvárať a odstraňovať zostavovacie potrubia cez docker daemon socket, ktorý je doň odovzdaný. Tento nápad sa mi páčil, ale rozhodol som sa ísť ďalej a skúsiť experimentovať s priamym spustením Dockera v Dockeri. Vtedy sa mi zdalo úplne logické riešenie stiahnuť si obrázky Docker a vytvoriť kontajnery pre všetky aplikácie, ktoré som potreboval na testovanie vo vnútri iného kontajnera (nazvime to stagingový kontajner). Myšlienkou bolo spustiť prípravný kontajner s príznakom -rm, ktorý po zastavení automaticky vymaže celý kontajner a celý jeho obsah. Pohral som si s obrázkom Docker zo samotného Dockera (https://hub.docker.com/_/docker), ale ukázalo sa, že je to príliš ťažkopádne a nikdy sa mi nepodarilo, aby to fungovalo tak, ako som potreboval a sám som chcel ísť celú cestu.

Prax. Šišky

Dal som si za cieľ, aby nádoba fungovala tak, ako som potrebovala, a pokračovala som v experimentoch, ktorých výsledkom bolo nespočetné množstvo púčikov. Výsledkom môjho sebatrýznenia bol nasledujúci algoritmus:

  1. Kontajner Docker spustíme v interaktívnom režime.

    docker run --privileged -it docker:18.09.6

    Venujte pozornosť verzii nádoby, urobte krok doprava alebo doľava a váš DinD sa zmení na tekvicu. V skutočnosti sa veci pokazia pomerne často, keď vyjde nová verzia.
    Musíme sa okamžite dostať do škrupiny.

  2. Snažíme sa zistiť, ktoré kontajnery sú spustené (odpoveď: žiadne), ale aj tak príkaz spustíme:

    docker ps

    Budete trochu prekvapení, ale ukáže sa, že démon Docker ani nebeží:

    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. Poďme to spustiť sami:

    dockerd &

    Ďalšie nepríjemné prekvapenie:

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

  4. Nainštalujte balíky iptables a bash (v bash je všetko príjemnejšie ako v sh):

    apk add --no-cache iptables bash

  5. Spustíme bash. Konečne sme späť v bežnej ulite

  6. Skúsme znova spustiť Docker:

    dockerd &

    Mali by sme vidieť dlhý list denníkov končiaci na:

    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. Stlačte Enter. Sme späť v bash.

Odteraz sa môžeme pokúsiť spustiť ďalšie kontajnery v našom kontajneri Docker, ale čo ak chceme spustiť ďalší kontajner Docker v našom kontajneri Docker alebo sa niečo pokazí a kontajner zlyhá? Začnite odznova.

Vlastný kontajner DinD a nové experimenty

Ako som spustil Docker v Dockeri a čo z toho vyšlo
Aby som sa vyhol opakovaniu vyššie uvedených krokov znova a znova, vytvoril som si vlastný kontajner DinD:

https://github.com/alekslitvinenk/dind

Pracovné riešenie DinD mi dalo možnosť rekurzívne spúšťať Docker vo vnútri Dockera a robiť dobrodružnejšie experimenty.
Jeden taký (úspešný) experiment s prevádzkovaním MySQL a Nodejs teraz popíšem.
Tí najnetrpezlivejší sa môžu pozrieť, ako to tu bolo

Začnime teda:

  1. DinD spúšťame v interaktívnom režime. V tejto verzii DinD musíme manuálne zmapovať všetky porty, ktoré môžu naše podriadené kontajnery používať (už na tom pracujem)

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

    Dostaneme sa do bash, odkiaľ môžeme okamžite začať spúšťať detské kontajnery.

  2. Spustite MySQL:

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

  3. K databáze sa pripájame rovnakým spôsobom, ako by sme sa k nej pripájali lokálne. Uistime sa, že všetko funguje.

  4. Spustite druhý kontajner:

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

    Upozorňujeme, že mapovanie portov bude presné 8080:8080, keďže sme už namapovali port 80 z hostiteľa do nadradeného kontajnera na port 8080.

  5. V prehliadači prejdeme na localhost a uistite sa, že server odpovedá "Ahoj svet!"

V mojom prípade experiment s vnorenými kontajnermi Docker dopadol celkom pozitívne a projekt budem ďalej rozvíjať a využívať na staging. Zdá sa mi, že je to oveľa odľahčenejšie riešenie ako Kubernetes a Jenkins X. Ale toto je môj subjektívny názor.

Myslím, že to je pre dnešný článok všetko. V ďalšom článku podrobnejšie popíšem experimenty s rekurzívnym spúšťaním Dockera v Dockeri a pripájaním adresárov hlboko do vnorených kontajnerov.

PS Ak považujete tento projekt za užitočný, dajte mu hviezdičku na GitHub, rozdeľte ho a povedzte to svojim priateľom.

Upraviť1 Opravené chyby, zameraná na 2 videá

Zdroj: hab.com

Pridať komentár