Të gjithëve përshëndetje! Në këtë , premtova se do të flas për ekzekutimin e Docker brenda Docker dhe për aspektet praktike të këtij aktiviteti. Ka ardhur koha për ta mbushur premtimin tim. Një devops i përvojës, ndoshta do të argumentonte se ata që kanë nevojë për Docker brenda Docker-it, thjesht kalojnë soketin e demonit Docker nga hosti në brendësi të kontejnerit dhe kjo është e mjaftueshme në 99% të rasteve. Por mos shpejtoni të më hidhni biskota, sepse do të flasim për një ekzekutim të vërtetë të Docker brenda Docker. Ky zgjidhje ka shumë fusha të mundshme përdorimi dhe një prej tyre do të përmendet në këtë artikull, prandaj vendosuni rehat dhe shtrini duar mbi tavolinë.

Fillimi
E gjitha filloi një mbrëmje me shi në Shtator, kur isha duke pastruar një makinë të marrë me qira për $5 në Digital Ocean, e cila u bllokua sepse Docker kishte mbushur të gjithë 24 gigabajt hapësirë të disponueshme me imazhe dhe kontejnerë. Ironia ishte se të gjitha këto imazhe dhe kontejnerë ishin transientë dhe nevojiteshin vetëm për të testuar funksionalitetin e aplikacionit tim çdo herë që dilte një version i ri i ndonjë biblioteke apo framorku. Provova të shkruaj skripta shell dhe të konfigur lindin një planifikues cron për të pastruar mbeturinat, por kjo nuk ndihmoi: çdo herë, gjithçka përfundonte me hapësirën disku të serverit tim duke u konsumuar dhe serveri duke ngecur (në rastin më të mirë). Në një moment, ndesha një artikull për se si të ekzekutoni Jenkins në një kontejner dhe se si ai mund të krijojë dhe fshijë kanale ndërtimi përmes soketit të demonit Docker të kaluar në të. Ideja më pëlqeu, por vendosa të shkoj më tej dhe të provoj të eksperimentoj me ekzekutimin e drejtpërdrejtë të Docker brenda Docker. Më pas, më dukej një zgjidhje e arsyeshme të shkarkoja imazhet Docker dhe të krijoja kontejnerë për të gjitha aplikacionet që më nevojiteshin për testim brenda një kontejneri tjetër (le të e quajmë kontejner staging). Ideja ishte të ekzekutoja kontejnerin staging me flamurin -rm, që automatikisht fshin të gjithë kontejnerin me të gjithë përmbajtjen e tij kur ndalet. U përpoqa me imazhin Docker të vetë Docker-it (), por ai doli të ishte shumë i rëndë dhe nuk arrita ta bëj të funksiononte ashtu siç e kisha dëshiruar dhe desha të eci nëpër tërë procesin vetë.
Praktika. Hapësira
Kisha e kam nxjerrë për qëllim të bëj që kontejneri të funksionojë siç kam nevojë dhe kam vazhduar eksperimentet e mia, rezultatet e të cilave ishin një numër i madh gabimesh. Përfundimi i vetë-ngacmimit tim ishte algoritmi i mëposhtëm:
Vijmë në kontejnerin Docker në modin interaktiv.
docker run --privileged -it docker:18.09.6Kujdesi nga versioni i kontejnerit, një hap majtas ose djathtas dhe DinD juaj kthehet në pumpkin. Në të vërtetë, gjithçka prishët shumë shpesh me daljen e një versioni të ri.
Duhet të hyjmë menjëherë në shell.Provojmë të mësojmë se cilët kontejnerë janë aktivë (Përgjigjja: asnjë), por le të zbatojmë komandën gjithsesi:
docker psDo të jeni pak të habitur, por duket se demoni Docker nuk është as aktivizuar:
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 befasi e pakëndshme:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundInstalojmë paketat iptables dhe bash (në bash gjithmonë është më mirë sesa në sh):
apk add --no-cache iptables bashVijmë në bash. Në fund kemi sërish në shell-in tonë të njohur.
provojmë të fillojmë Docker përsëri:
dockerd &Duhet të shohim një rresht të gjatë log-esh që përfundon me:
INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sockShtypim Enter. Jemi përsëri në bash.
Që nga ky moment mund të fillojmë të aktivizojmë kontejnerë të tjerë brenda kontejnerit tonë Docker, por çfarë nëse duam të ngremë një tjetër kontejner Docker brenda kontejnerit tonë Docker ose diçka shkon keq dhe kontejneri "del"? Të fillojmë gjithçka nga e para.
Kontejneri im DinD dhe eksperimentet e reja.
Për të mos përsëritur hapat e përmendur më lart përsëri dhe përsëri, kam krijuar kontejnerin tim DinD:
Zgjidhja funksionale DinD më ka mundësuar të aktivizoj Docker brenda Docker-it në mënyrë rekursive dhe të kryej eksperimentet më guximtare.
Një nga këto eksperimente (të suksesshme) me aktivizimin e MySQL dhe Nodejs do ta përshkruaj tani.
Ata që nuk kanë durim mund ta shohin si ndodhi këtu

Pra, le të fillojmë:
Vijmë në DinD në modin interaktiv. Në këtë version DinD na nevojitet të mapojmë manualisht të gjitha portet që mund të përdorin kontejnerët tanë të bij.
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindNe hyjmë në bash, nga ku mund të fillojmë menjëherë me lançimin e kontejnerëve dytësorë.
Fillojmë 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 ta bënim lokal. Sigurohemi që gjithçka funksionon.
Fillojmë kontejnerin e dytë:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverVini re se mapimi i portit këtu do të jetë konkretisht 8080:8080, pasi kemi mapuar portin 80 nga hosti në kontejnerin prind në portin 8080.
Shkoni në localhost në shfletues, sigurohuni që serveri përgjigjet "Hello World!".
Në rastin tim, eksperimenti me kontejnerët Docker të vendosur brenda njëri-tjetrit doli të ishte mjaft pozitiv dhe do të vazhdoj ta zhvilloj projektin dhe ta përdor për staging. Më duket se kjo është një zgjidhje shumë më e lehtë se Kubernetes dhe Jenkins X. Por kjo është opinioni im subjektiv.
Mendoj se për artikullin e sotëm, kjo është e gjitha. Në artikullin e ardhshëm do të përshkruaj më hollësisht eksperimentet me lançimin rekurziv të Dockerit brenda Dockerit dhe montimin e direktorive në thellësi të kontejnerëve të vendosur brenda.
P.S. Nëse e konsideroni këtë projekt të dobishëm, ju lutem jepni një yll në GitHub, bëni fork dhe tregoni miqve tuaj.
Edit1 Korrigjova gabimet, vendosa theksin në 2 video
Burimi: habr.com
