Jak jsem spustil Docker uvnitř Dockeru a co z toho vzešlo

Ahoj všichni! Ve svém předchozí článku, slíbil jsem, že se podělím o spuštění Dockera v Dockeru a o praktických aspektech aplikace této činnosti. Nastal čas splnit svůj slib. Zkušený DevOps by snad mohl nesouhlasit a říci, že ti, kdo potřebují Docker uvnitř Dockera, jednoduše přesměrují socket Docker démona z hostitele dovnitř kontejneru, což stačí v 99 % případů. Ale nespěchejte na mě házet sušenky, protože se bude jednat o skutečné spuštění Dockera uvnitř Dockera. Toto řešení má mnoho možných oblastí aplikace a o jednom z nich je tento článek, takže se usaďte pohodlně a vyrovnejte si ruce před sebe.

Jak jsem spustil Docker uvnitř Dockeru a co z toho vzešlo

Začátek

Všechno začalo deštivým zářijovým večerem, když jsem čištěl pronajatý stroj za 5 USD na Digital Ocean, který zamrzl, protože Docker zaplnil svými obrazy a kontejnery všech 24 gigabajtů dostupného úložiště. Ironií bylo, že všechny tyto obrazy a kontejnery byly transientní a potřeboval jsem je jen k testování funkčnosti mé aplikace pokaždé, když vyšla nová verze nějaké knihovny či frameworku. Zkoušel jsem psát shell skripty a nastavovat cron pro úklid odpadu, ale to nepomohlo: pokaždé to nevyhnutelně končilo tím, že diskový prostor mého serveru byl zacenžován a server zamrzl (v tom lepším případě). V určitém okamžiku jsem narazil na článek o tom, jak spouštět Jenkins v kontejneru a jak může vytvářet a odstraňovat build pipeline přes přesměrovaný socket docker démona. Nápad se mi zalíbil, ale rozhodl jsem se zajít dál a vyzkoušet experimentovat s přímým spuštěním Dockera uvnitř Dockera. V té době se mi zdálo zcela logickým řešením stahovat docker obrazy a vytvářet kontejnery všech aplikací, které potřebuji pro testování uvnitř jiného kontejneru (nazvěme ho staging kontejner). Nápad spočíval v tom, spouštět staging kontejner s příznakem -rm, což automaticky odstraní celý kontejner se vším jeho obsahem při jeho zastavení. Zkoumal jsem docker obraz od samotného Dockera (https://hub.docker.com/_/docker), ale zjistil jsem, že je příliš objemný a nepodařilo se mi donutit ho pracovat tak, jak potřebuji, a chtěl jsem si projít celou cestu sám.

Praxe. Případné problémy

Stanovil jsem si za cíl dostat kontejner do provozu tak, jak jsem potřeboval, a pokračoval jsem ve svých experimentech, jejichž výsledkem bylo nespočet vylepšení. Výsledkem mého sebevzdělávání byl následující algoritmus:

  1. Spouštíme Docker kontejner v interaktivním režimu.

    docker run --privileged -it docker:18.09.6

    Všimněte si verze kontejneru, krok vpravo nebo vlevo a váš DinD se mění na dýni. Ve skutečnosti se to často pokazí s vydáním nové verze.
    Musíme se okamžitě dostat do shellu.

  2. Zkusíme zjistit, které kontejnery jsou spuštěny (Odpověď: žádné), ale pojďme provést příkaz stejně:

    docker ps

    Budete trochu překvapeni, ale ukazuje se, že Docker démon ani neběží:

    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. Pojďme to spustit sami:

    dockerd &

    Další nepříjemné překvapení:

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

  4. Instalujeme balíčky iptables a bash (v bash je příjemnější pracovat než v sh):

    apk add --no-cache iptables bash

  5. Spouštíme bash. Konečně jsme zpět v obvyklém shellu.

  6. zkusíme spustit Docker znovu:

    dockerd &

    Musíme vidět dlouhý výpis logů končící:

    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. Stiskneme Enter. Jsme znovu v bash.

Od tohoto okamžiku můžeme zkoušet spouštět další kontejnery uvnitř našeho Docker kontejneru, ale co když chceme spustit další Docker kontejner uvnitř našeho Docker kontejneru nebo něco nevyjde a kontejner "vypadne"? Začít znovu.

Vlastní DinD kontejner a nové experimenty.

Jak jsem spustil Docker uvnitř Dockeru a co z toho vzešlo
Abych nemusel znovu a znovu opakovat výše popsané kroky, vytvořil jsem vlastní DinD kontejner:

https://github.com/alekslitvinenk/dind

Fungující DinD řešení mi umožnilo spouštět Docker uvnitř Dockeru rekurzivně a provádět odvážnější experimenty.
Jeden takový (úspěšný) experiment se spuštěním MySQL a Nodejs nyní popíšu.
Nejvíce netrpěliví si mohou prohlédnout, jak to bylo zde.

Přehrát video

Tak začněme:

  1. Spouštíme DinD v interaktivním režimu. V této verzi DinD musíme ručně namapovat všechny porty, které mohou používat naše podřízené kontejnery (na tom již pracuji).

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

    Dostáváme se do bash, odkud můžeme okamžitě začít spouštět podřízené kontejnery.

  2. Spouštíme MySQL:

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

  3. Připojujeme se k databázi stejně jako bychom se k ní připojovali lokálně. Ujistíme se, že vše funguje.

  4. Spouštíme druhý kontejner:

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

    Všimněte si, že mapování portu zde bude právě 8080:8080, protože jsme již namapovali port 80 z hostitele do rodičovského kontejneru na port 8080.

  5. Jdeme na localhost v prohlížeči a ujistíme se, že server odpovídá "Hello World!".

V mém případě experiment s vloženými Docker kontejnery dopadl docela pozitivně a budu pokračovat v rozvoji projektu a jeho používání pro staging. Zdá se mi, že je to mnohem lehčí řešení než Kubernetes a Jenkins X. Ale to je můj subjektivní názor.

Myslím, že pro dnešní článek je to vše. V dalším článku podrobněji popíšu experimenty s rekurzivním spuštěním Dockeru v Dockeru a montování adresářů do hloubky vložených kontejnerů.

P.S. Pokud považujete tento projekt za užitečný, prosím, dejte mu hvězdičku na GitHubu, udělejte fork a řekněte o něm přátelům.

Edit1 Opravil jsem chyby, zaměřil jsem se na 2 videa

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster