Ahoj všichni! V jeho
začátek
Všechno to začalo jednoho deštivého zářijového večera, když jsem čistil stroj, který jsem si pronajal za 5 dolarů na Digital Ocean, který byl zamrzlý kvůli skutečnosti, že Docker svými obrázky a kontejnery zaplnil všech 24 gigabajtů dostupného místa na disku. Ironií bylo, že všechny tyto obrázky a kontejnery byly přechodné a byly potřeba pouze k testování výkonu mé aplikace pokaždé, když byla vydána nová verze knihovny nebo frameworku. Zkoušel jsem psát skripty shellu a nastavit plán cron na čištění odpadků, ale nepomohlo to: pokaždé to nevyhnutelně skončilo tím, že se mi zabralo místo na disku a server se zastavil (v nejlepším případě). V určitém okamžiku jsem narazil na článek o tom, jak spustit Jenkins v kontejneru a jak může vytvářet a odstraňovat sestavení potrubí přes docker daemon socket předaný do něj. Nápad se mi líbil, ale rozhodl jsem se jít dále a zkusit experimentovat s přímým spuštěním Dockeru uvnitř Dockeru. V té době se mi zdálo zcela logické řešení stáhnout si obrazy Dockeru a vytvořit kontejnery pro všechny aplikace, které jsem potřeboval pro testování uvnitř jiného kontejneru (říkejme tomu staging kontejner). Záměrem bylo spustit pracovní kontejner s parametrem -rm, který po zastavení automaticky odstraní celý kontejner a veškerý jeho obsah. Pohrál jsem si s obrázkem Dockeru ze samotného Dockeru (
Praxe. Šišky
Rozhodl jsem se, že nádoba bude fungovat tak, jak jsem potřeboval, a pokračoval ve svých experimentech, které vyústily v nesčetné množství pupenů. Výsledkem mého sebetrýznění byl následující algoritmus:
-
Spustíme kontejner Docker v interaktivním režimu.
docker run --privileged -it docker:18.09.6
Věnujte pozornost verzi nádoby, krok vpravo nebo vlevo a váš DinD se promění v dýni. Ve skutečnosti se věci pokazí poměrně často, když je vydána nová verze.
Musíme se okamžitě dostat do skořápky. -
Snažíme se zjistit, které kontejnery běží (odpověď: žádné), ale přesto spusťte příkaz:
docker ps
Budete trochu překvapeni, ale ukáže se, že démon Docker 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
-
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
-
Nainstalujte balíčky iptables a bash (všechno je příjemnější pracovat v bash než v sh):
apk add --no-cache iptables bash
-
Spustíme bash. Konečně jsme zpět v obvyklé skořápce
-
Zkusme znovu spustit Docker:
dockerd &
Měli bychom vidět dlouhý list protokolů končící 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
-
Stiskněte Enter. Jsme zpět v bash.
Od této chvíle se můžeme pokusit spustit další kontejnery v našem kontejneru Docker, ale co když chceme spustit další kontejner Docker v našem kontejneru Docker nebo se něco pokazí a kontejner se zhroutí? Začněte znovu.
Vlastní kontejner DinD a nové experimenty
Abych se vyhnul opakování výše uvedených kroků znovu a znovu, vytvořil jsem svůj vlastní kontejner DinD:
Funkční řešení DinD mi dalo možnost spouštět Docker uvnitř Dockeru rekurzivně a dělat dobrodružnější experimenty.
Jeden takový (úspěšný) experiment se spuštěním MySQL a Nodejs teď popíšu.
Ti největší nedočkavci se mohou podívat, jak to tady bylo
Začněme tedy:
-
Spouštíme DinD v interaktivním režimu. V této verzi DinD musíme ručně namapovat všechny porty, které mohou naše podřízené kontejnery používat (už na tom 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 dětské kontejnery.
-
Spusťte MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql
-
K databázi se připojujeme stejným způsobem, jako bychom se k ní připojovali lokálně. Ujistíme se, že vše funguje.
-
Spusťte druhý kontejner:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server
Upozorňujeme, že mapování portů bude přesné 8080:8080, protože jsme již namapovali port 80 z hostitele do nadřazeného kontejneru na port 8080.
-
V prohlížeči přejdeme na localhost a ujistěte se, že server odpovídá "Hello World!"
V mém případě dopadl experiment s vnořenými kontejnery Docker vcelku pozitivně a projekt budu dále rozvíjet a používat pro staging. Zdá se mi, že je to mnohem odlehčenější řešení než Kubernetes a Jenkins X. Ale to je můj subjektivní názor.
Myslím, že to je pro dnešní článek vše. V příštím článku popíšu podrobněji experimenty s rekurzivním spouštěním Dockeru v Dockeru a připojováním adresářů hluboko do vnořených kontejnerů.
PS Pokud považujete tento projekt za užitečný, dejte mu hvězdičku na GitHubu, rozklikněte jej a řekněte to svým přátelům.
Edit1 Opraveny chyby, zaměřeno na 2 videa
Zdroj: www.habr.com