Bok svima! U njegovom Obećao sam da ću govoriti o pokretanju Dockera unutar Dockera i praktičnim aspektima ove vježbe. Vrijeme je da ispunim to obećanje. Iskusni DevOps profesionalac mogao bi tvrditi da oni kojima je potreban Docker unutar Dockera jednostavno proslijede Docker daemon socket s hosta na kontejner i to je dovoljno u 99% slučajeva. Ali nemojte žuriti bacati kolačiće na mene, jer govorimo o stvarnom pokretanju Dockera unutar Dockera. Ovo rješenje ima mnogo potencijalnih primjena, a ovaj članak je o jednoj od njih, stoga se udobno smjestite i ispružite ruke ispred sebe.

početak
Sve je počelo jedne kišne rujanske večeri dok sam čistio stroj od 5 dolara koji sam unajmio na Digital Oceanu, a koji se zamrznuo zbog Docker slika i kontejnera koji su popunili svih 24 gigabajta dostupnog prostora na disku. Ironija je bila u tome što su sve te slike i kontejneri bili prolazni i potrebni su samo za testiranje funkcionalnosti moje aplikacije svaki put kada bi se objavila nova verzija biblioteke ili okvira. Pokušao sam pisati shell skripte i postaviti cron zadatak za čišćenje smeća, ali nije pomoglo: svaki put bi neizbježno završilo time što bi prostor na disku mog poslužitelja bio pojeden i poslužitelj bi se zamrznuo (u najboljem slučaju). U nekom trenutku naišao sam na članak o tome kako pokrenuti Jenkins u kontejneru i kako može stvarati i brisati cjevovode izgradnje putem Docker daemon socketa koji mu je izložen. Svidjela mi se ideja, ali odlučio sam otići korak dalje i eksperimentirati s pokretanjem Dockera izravno unutar Dockera. Tada mi se činilo logičnim rješenjem preuzeti Docker slike i stvoriti kontejnere svih aplikacija koje su mi potrebne za testiranje unutar drugog kontejnera (nazovimo ga staging kontejner). Ideja je bila pokrenuti kontejner za pripremu s opcijom -rm, koja automatski briše cijeli kontejner i sav njegov sadržaj kada se zaustavi. Malo sam istraživao sliku Dockera iz samog Dockera (), ali se pokazalo previše kompliciranim i nikad ga nisam uspio natjerati da funkcionira onako kako mi je trebalo, a htio sam sam proći kroz cijeli proces.
Vježba. Čunjevi
Krenuo sam u namjeri da posuda funkcionira onako kako mi je potrebno i nastavio sam svoje eksperimente, što je rezultiralo bezbrojnim problemima. Kulminacija mog samomučenja bio je sljedeći algoritam:
Pokrećemo Docker kontejner u interaktivnom načinu rada.
docker run --privileged -it docker:18.09.6Obratite pozornost na verziju kontejnera. Jedan korak udesno ili ulijevo i vaš DinD se pretvara u bundevu. Zapravo, stvari se prilično često pokvare kada se objavi nova verzija.
Moramo odmah ući u oklop.Pokušajmo saznati koji se kontejneri izvode (odgovor: nijedan), ali svejedno pokrenimo naredbu:
docker psBit ćete malo iznenađeni, ali ispada da Docker daemon uopće ne radi:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such hostPokrenimo to sami:
dockerd &Još jedno neugodno iznenađenje:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundInstalirajte pakete iptables i bash (rad u bashu je definitivno ugodniji nego u sh-u):
apk add --no-cache iptables bashPokrenimo bash. Konačno smo se vratili u našu poznatu ljusku.
Pokušajmo ponovno pokrenuti Docker:
dockerd &Trebali bismo vidjeti dugi list logova koji završava s:
INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sockPritisnite Enter. Vratili smo se u toranj.
Od ove točke nadalje, možemo pokušati pokrenuti druge kontejnere unutar našeg Docker kontejnera, ali što ako želimo pokrenuti još jedan Docker kontejner unutar našeg Docker kontejnera ili nešto pođe po zlu i kontejner se sruši? Moramo početi ispočetka.
Vlastiti DinD kontejner i novi eksperimenti
Kako bih izbjegao ponavljanje gore navedenih koraka iznova i iznova, stvorio sam vlastiti DinD kontejner:
Posjedovanje funkcionalnog DinD rješenja omogućilo mi je rekurzivno pokretanje Dockera unutar Dockera i provođenje avanturističkijih eksperimenata.
Sada ću opisati jedan takav (uspješan) eksperiment s pokretanjem MySQL-a i Nodejsa.
Najnestrpljiviji mogu vidjeti kako je ovdje bilo

Dakle, krenimo:
DinD ćemo pokrenuti u interaktivnom načinu rada. U ovoj verziji DinD-a moramo ručno mapirati sve portove koje naši podređeni kontejneri mogu koristiti (već radim na tome).
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindUlazimo u bash, odakle možemo odmah početi pokretati podkontejnere.
Pokrenite MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlSpojite se na bazu podataka na isti način kao što bismo se spojili lokalno. Provjerite da sve radi.
Pokrećemo drugi kontejner:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverImajte na umu da će mapiranje portova ovdje biti točno 8080:8080, budući da smo već mapirali port 80 s hosta na nadređeni kontejner na portu 8080.
Idite na localhost u pregledniku i provjerite odgovara li poslužitelj s "Pozdrav svijete!".
U mom slučaju, eksperiment s ugniježđenim Docker kontejnerima bio je prilično pozitivan i nastavit ću razvijati projekt i koristiti ga za pripravu. Vjerujem da je to puno lakše rješenje od, recimo, Kubernetesa i Jenkinsa X. Ali to je samo moje subjektivno mišljenje.
Mislim da je to sve za današnji članak. U sljedećem članku detaljnije ću opisati eksperimente s rekurzivnim Docker startupima u Dockeru i montiranjem direktorija duboko unutar ugniježđenih kontejnera.
PS Ako smatrate ovaj projekt korisnim, molimo vas da mu date zvjezdicu na GitHubu, podijelite ga s prijateljima.
Edit1 Ispravljene su neke greške i fokusiranje na 2 videa.
Izvor: www.habr.com
