Përshëndetje të gjithëve! Në , e premtova se do të flas për përdorimin e Docker-it brenda Docker-it dhe aspektet praktike të përdorimit të kësaj aktiviteti. Ka ardhur koha për të plotësuar premtimin tim. Një DevOps i njohur mund të kundërshtojë se ata që kanë nevojë për Docker brenda Docker-it thjesht hapin një socket të demonit Docker nga hosti brenda kontejnerit dhe kjo mjafton në 99% të rasteve. Por mos e lëshoni atë për mua, sepse do të flasim për një përdorim real të Docker-it brenda Docker-it. Ky zgjidhje ka shumë fusha të mundshme të aplikimit dhe për njërën prej tyre është kjo artikull, prandaj uleni rehat dhe shtrini duar tuaj përpara.

Fillimi
Të gjitha filloi në një mbrëmje të lagësht shtatori, kur po pastronte një makinë me qira për $5 në Digital Ocean, e cila ngeci për shkak se Docker mbushte të gjithë 24 gigabajt të hapësirës diskore me imazhe dhe kontejnerë. Ironia ishte se të gjitha këto imazhe dhe kontejnerë ishin tranzitore dhe nevojiteshin vetëm për të testuar funksionalitetin e aplikacionit tim çdo herë që dilte një version i ri i ndonjë biblioteke ose frameworku. Pata provuar të shkruaj skripte shell dhe të konfiguroj një orar cron për të pastruar plehrat, por kjo nuk ndihmoi: çdo herë çdo gjë përfundonte me hapësirën diskore të serverit tim duke u ngrënë dhe serveri duke ngecur (në rastin më të mirë). Në një moment, ndesha një artikull mbi mënyrën e funksionimit të Jenkins në një kontejner dhe se si ai mund të krijonte dhe fshinte pipeline-t e ndërtimit përmes një socket-i të kaluar në demonin e Docker-it. Ideja më pëlqeu, por vendosa të shkoj më tej dhe të provoj të eksperimentoj me ekzekutimin e Docker-it brenda Docker-it. Më dukej si një zgjidhje logjike të shkarkonte imazhet docker dhe të krijonte kontejnerët e të gjitha aplikacioneve që më nevojiteshin për testim brenda një kontejneri tjetër (le ta quajmë kontejnerin staging). Ideja ishte që të niste kontejnerin staging me flamurin -rm, i cili automatikisht fshin të gjithë kontejnerin me të gjitha përmbajtjet e tij kur ndalon. Hipoteza ime ishte të luaja me imazhin docker të vetë Docker-it.), por megjithatë doli të ishte shumë e rëndë dhe nuk arrita asnjëherë ta bëja të punojë siç doja dhe doja të kaloja të gjithë rrugën vetë.
Praktika. Goditjet
Kisha për qëllim të bëja që kontejneri të punonte siç e doja dhe vazhdova eksperimentet e mia, rezultati i të cilave ishte një numër i pafund “goditjesh”. Rezultati i vetë-masakrës time ishte algoritmi i mëposhtëm:
Nisim kontejnerin Docker në modin interaktiv.
docker run --privileged -it docker:18.09.6Kujdesuni për versionin e kontejnerit, një hap djathtas ose majtas dhe Dind juaj shndërrohet në një kungull. Në të vërtetë, gjithçka prishët mjaft shpesh me daljen e versioneve të reja.
Duhet të hyjmë menjëherë në shell.Provo të zbardhësh se cilët kontenjerë janë të incizuar (Përgjigja: asnjë), por le të ekzekutojmë komandën gjithsesi:
docker psDo të befasohesh pak, por rezulton që demoni Docker asl më nuk është nisur:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such hostLe të fillojmë atë vetë:
dockerd &Një tjetër surprizë e pakëndshme:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundInstallojmë paketat iptables dhe bash (në bash gjithçka funksionon më mirë se në sh):
apk add --no-cache iptables bashNisim bash. Më në fund jemi prapë në shell-in tonë të njohur.
Të provojmë të nisim Docker-in përsëri:
dockerd &Duhet të shohim një listë të gjatë log-esh që përfundojnë me:
INFO[2019-11-25T19:51:19.448080400Z] Daemon ka përfunduar inicializimin INFO[2019-11-25T19:51:19.474439300Z] API dëgjon në /var/run/docker.sockShtypni Enter. Jemi përsëri në bash.
Që nga ky moment mund të provojmë të nisim kontejnerë të tjerë brenda kontejnerit tonë Docker, por çfarë nëse duam të ngrisim një tjetër kontejner Docker brenda kontejnerit tonë Docker ose diçka shkon keq dhe kontejneri "ndal"? Të fillojmë gjithçka nga e para.
Kontejneri im DinD dhe eksperimente të reja.
Për të mos përsëritur hapat e mësipërm vazhdimisht, krijova kontejnerin tim DinD:
Zgjidhja funksionale DinD më dha mundësinë të nisim Docker brenda Docker-it në mënyrë rekursive dhe të kryej eksperimente më të guximshme.
Një eksperiment i tillë (i suksesshëm) me nisim MySQL dhe Nodejs do të përshkruaj tani.
Të padurueshmit mund ta shikojnë se si ndodhi këtu:

Pra, le të fillojmë:
Nisim DinD në mod interaktiv. Në këtë version të DinD, na nevojitet të mapojmë manualisht të gjitha portet që mund të përdorin kontejnerët tanë të nënës (po punoj mbi këtë).
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindKemi hyrë në bash, nga ku mund të fillojmë menjëherë me nisjen e kontejnerëve nënës.
Nisim MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlLidhemi me bazën e të dhënave ashtu siç do të lidhemi me të lokal. Sigurohemi që gjithçka të funksionojë.
Nisim kontejnerin e dytë:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverKujdes, se ndërsa porti i mapimit këtu do të jetë pikërisht 8080:8080, pasi tashmë e kemi mapuar portin 80 nga hosti në kontejnerin prind në portin 8080.
Shkojmë në localhost të shfletuesi, sigurohemi që serveri përgjigjet 'Hello World!'.
Në rastin tim, eksperimentimi me kontejnerët Docker të enkas rezultoi mjaft pozitiv dhe do të vazhdoj ta zhvilloj projektin dhe ta përdor këtë për staging. Më duket se është një zgjidhje shumë më e lehtë se Kubernetes dhe Jenkins X. Por kjo është mendimi im subjektiv.
Mendoj se kjo është e gjitha për artikullin e sotëm. Në artikullin e ardhshëm do të përshkruaj më thellësisht eksperimentet me nisjen rekurzive të Docker-it brenda Docker-it dhe montimin e drejtorive në thellësi të kontejnerëve të ndërlidhur.
P.S. Nëse e konsideroni këtë projekt të dobishëm, ju lutem jepni një yll në GitHub, bëni forku dhe tregoni miqve tuaj.
Edit1 Korrigjova gabimet, fokusova në 2 video
Burimi: habr.com
