
Docker-in-Docker paraqet një ambient të virtualizuar Docker-demon, i ekzekutuar brenda vetë kontejnerit për ndërtimin e imazheve të kontejnerëve. Qëllimi kryesor i krijimit të Docker-in-Docker ishte ndihma në zhvillimin e vetë Dockerit. Shumë njerëz e përdorin atë për të ekzekutuar Jenkins CI. Në fillim duket normale, por më pas shfaqen probleme që mund të shmangen duke instaluar Docker brenda kontejnerit Jenkins CI. Ky artikull shpjegon se si ta bëni këtë. Nëse jeni të interesuar për zgjidhjen përfundimtare pa detaje, thjesht lexoni seksionin e fundit të artikullit "Zgjidhja e problemit".

Docker-in-Docker: «I Mirë»
Më shumë se dy vjet më parë, unë përfshiva në Docker -privilegjuar dhe shkrova . Qëllimi ishte që t'i ndihmoj ekipit kryesor të zhvillonte më shpejt Dockerin. Para se të ndodhte Docker-in-Docker, cikli tipik i zhvillimit ishte si më poshtë:
- hackity hack;
- ndërtimi (build);
- ndalimi i Docker-demonit të ekzekutuar;
- njoftimi i një Docker-demon të ri;
- testimi;
- ripërsëritja e ciklit.
Por nëse donit të bënit një ndërtim të bukur, të riprodhueshëm (pra, brenda kontejnerit), ato bëheshin më të ndërlikuara:
- hackity hack;
- sigurimi që versioni funksional i Docker ishte i ekzekutuar;
- ndërtoni një Docker të ri me Dockerin e vjetër;
- ndaloni demonin Docker;
- nisni demonin e ri Docker;
- testoni;
- ndaloni demonin e ri Docker;
- përsëritni.
Me shfaqjen e Docker-in-Docker, procesi është bërë më i thjeshtë:
- hackity hack;
- ndërtimi + nisja në një hap;
- ripërsëritja e ciklit.
A nuk është kështu shumë më mirë?

Docker-in-Docker: «I keqi»
Sidoqoftë, përkundër mendimit të zakonshëm, Docker-in-Docker nuk është 100% yje, ponj dhe njëhorna. Kam parasysh se ka disa probleme që zhvilluesi duhet të dijë.
NjĂ«ra prej tyre ka tĂ« bĂ«jĂ« me LSM (modulet e sigurisĂ« nĂ« Linux), si AppArmor dhe SELinux: gjatĂ« lançimit tĂ« kontejnerit, "Docker-i i brendshĂ«m" mund tĂ« pĂ«rpiqet tĂ« zbatojĂ« profile sigurie qĂ« do tĂ« krijonin konflikte ose konfuzion me "Docker-in e jashtĂ«m". Kjo ishte problemi mĂ« i komplikuar qĂ« duheshin zgjidhur kur pĂ«rpiqeshim tĂ« bashkonim implementimin origjinal tĂ« flag-ut âprivileged. Ndryshimet e mia funksiononin, dhe tĂ« gjitha testet do tĂ« kalonin nĂ« makinĂ«n time Debian dhe nĂ« makinat virtuale testuese tĂ« Ubuntu, por ato do tĂ« dĂ«shtonin dhe digjeshin nĂ« makinĂ«n e Michael Crosby-t (po tĂ« kujtohem saktĂ«, ai kishte Fedora). Nuk mund ta kujtoj arsyen eksakte tĂ« problemit, por ndoshta ndodhi sepse Mike Ă«shtĂ« njĂ« njeri i mençur, i cili punon me SELINUX=enforce (unĂ« pĂ«rdora AppArmor), dhe ndryshimet e mia nuk merrnin parasysh profilet e SELinux.
Docker-in-Docker: "E keqe"
Problemi i dytë është lidhur me driverët e ruajtjes Docker. Kur ju filloni Docker-in-Docker, Docker-i jashtë punon mbi sistemin e zakonshëm të skedarëve (EXT4, BTRFS ose ndonjë tjetër që keni), ndërsa Docker-i i brendshëm punon mbi sistemin e kopjimit gjatë shkrimit (AUFS, BTRFS, Device Mapper etj., në varësi të asaj që është konfiguruar për të përdorur Docker-i i jashtëm). Kjo krijon një shumëllojshmëri kombinimesh që nuk do të funksionojnë. Për shembull, nuk mund të nisin AUFS mbi AUFS.
Nëse po përdorni BTRFS mbi BTRFS, fillimisht duhet të funksionojë, por sapo të shfaqen nënndërçarjet, nuk do të jetë e mundur të hiqet nënndërçarja prind. Moduli Device Mapper nuk ka hapësirë emrash, kështu që, nëse disa instance Docker-i e përdorin atë në një makinë, të gjitha do të mund ta shohin (dhe ndikojnë) në imazhet e njëra-tjetrës dhe në pajisjet e rezervës për konteinerët. Kjo është e keqe.
Ka janë disa përzgjidhje për të zgjidhur shumë nga këto probleme. Për shembull, nëse dëshironi të përdorni AUFS në Dockerin tuaj të brendshëm, thjesht kthejeni dosjen /var/lib/docker në një volum dhe gjithçka do të shkojë në rregull. Docker ka shtuar disa hapësira bazë të emrave në emrat e synimeve të Mapper të Pajisjeve, kështu që nëse disa thirrje Docker kryhen në të njëjtën makinë, ato nuk do të 'ngjiten' mbi njëra-tjetrën.
Megjithatë, një konfigURATION e tillë nuk është e lehtë, siç mund të shihet nga këto në depozitën dind në GitHub.
Docker në Docker: bëhet edhe më keq
E çfarĂ« me cashin e ndĂ«rtimit? Kjo gjithashtu mund tĂ« jetĂ« mjaft e komplikuar. NjerĂ«zit shpesh mĂ« pyesin ânĂ«se po ekzekutoj Docker nĂ« Docker, si mund tĂ« pĂ«rdor imazhet qĂ« ndodhen nĂ« hostin tim, nĂ« vend qĂ« t'i sjell pĂ«rsĂ«ri tĂ« gjitha nĂ« Dockerin tim tĂ« brendshĂ«m?â
Disa njerëz sipërmarrës kanë përpiqur të lidhin /var/lib/docker nga hosti në konteinerin Docker në Docker. Ndonëse, ato shpesh ndajnë /var/lib/docker me disa konteinerë.

Dëshironi të dëmtosh të dhënat? Sepse kjo është pikërisht ajo që do të dëmtojë të dhënat tuaja!
Docker-dëmoni duket se është krijuar për të pasur qasje ekskluzive në /var/lib/docker. Asgjë tjetër nuk duhet "të prekë, gërmojë ose të zhyti" ndonjë skedar Docker që ndodhet në këtë dosje.
Pse është kështu? Sepse kjo është rezultat i një prej mësimeve më të vështira që kemi marrë gjatë zhvillimit të dotCloud. Mjet i konteinerëve të dotCloud ka punuar me disa procese që qasën njëkohësisht në /var/lib/dotcloud. Truket e mençura, si zëvendësimi atomik i skedave (në vend të redaktimit në vend), "spicing" e kodit me bllokime rekomanduese dhe të detyrueshme e eksperimente të tjera me sisteme të sigurta, si SQLite dhe BDB, nuk kanë funksionuar gjithmonë. Kur ne rishkruam mjetin tonë të konteinerëve, i cili përfundimisht u bë Docker, një nga vendimet kryesore të dizajnit ishte të grumbulloheshin të gjitha operacionet me konteinerët nën një demon të vetëm, për t'i dhënë fund gjithë kësaj marrëzie të aksesit njëkohësisht.
Mos ku e kuptoni gabim: është plotësisht e mundur të bëni diçka të mirë, të besueshme dhe të shpejtë, që përfshin disa procese dhe menaxhim bashkëkohor paralel. Por ne mendojmë se është më e lehtë dhe më e thjeshtë të shkruani dhe mbani kodin duke përdorur Docker si një lojtar të vetëm.
Kjo do të thotë se nëse ndihmoni një katalog /var/lib/docker ndërmjet disa instancave Docker, do të keni probleme. Sigurisht, kjo mund të funksionojë, veçanërisht në fazat e hershme të testeve. 'Dëgjo, Ma, mund ta nisim ubuntu me "docker"!' Por provo të bësh diçka më të komplikuar, për shembull, të nxjerrësh të njëjtin imazh nga dy instanca të ndryshme dhe do të shohësh si digjet bota.
Kjo do të thotë se nëse sistemi juaj CI kryen ndërtime dhe rindërtime, çdo herë që rinis një kontejner Docker-në-Docker rrezikoni të shkaktoni një shpërthim në cache të tij. Kjo nuk është aspak e këndshme!
Zgjidhja e problemit
Le të heqim një hap mbrapa. A ju nevojitet vërtet Docker-në-Docker apo thjesht dëshironi të keni mundësinë të nisim Docker, pra të ndërtoni dhe të nisni kontejnerë dhe imazhe nga sistemi juaj CI, kurse ky sistem CI vetë ndodhet brenda një kontejneri?
E sigurtë që shumicës së njerëzve u nevojitet versioni më i fundit, pra ata duan që sistemi CI, si Jenkins, të jetë në gjendje të drejtojë kontejnerët. Dhe mënyra më e thjeshtë për ta bërë këtë është të vendosni thjesht socket-in Docker në kontejnerin tuaj CI, duke e lidhur atë me flagun -v.
Thënë ndryshe, kur ekzekutoni kontejnerin tuaj CI (Jenkins ose ndonjë tjetër), në vend që të hidhni diçka duke përdorur Docker-in-Docker, filloni atë me komandën:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...Tani ky kontejner do të ketë qasje në socket-in Docker dhe, për pasojë, do të jetë në gjendje të drejtojë kontejnerët. Përveç se, në vend të lançimit të kontejnerëve 'fëmijë', ai do të lançojë kontejnerë 'të afërt'.
Provoni këtë, duke përdorur imazhin zyrtar docker (i cili përmban skedarin binar të Docker):
docker run -v /var/run/docker.sock:/var/run/docker.sock
-ti dockerKjo duket dhe funksionon si Docker-in-Docker, por nuk është Docker-in-Docker: kur ky kontejner krijon kontejnerë shtesë, ata do të krijohen në Docker-in-suprem. Nuk do të përjetoni efekte anësore të thellësisë, dhe nëndërtesa do të përdorë të njëjtin cache për disa thirrje.
Shënim: versionet e mëparshme të këtij artikulli rekomandonin lidhjen e një skedari binar Docker nga hosti në kontejner. Tani kjo është bërë e pasigurt, sepse mekanizmi Docker nuk zgjerohet më mbi bibliotekat statike ose pothuajse statike.
Prandaj, nëse dëshironi të përdorni Docker nga Jenkins CI, keni 2 mundësi:
instalimi i Docker CLI duke përdorur sistemin bazë të paketave të imazhit (dmth, nëse imazhi juaj bazohet në Debian, përdorni paketat .deb), përdorimi i Docker API.
Pak reklamĂ« đ
Faleminderit që qëndroni me ne. Ju pëlqejnë artikujt tanë? Dëshironi të shihni më shumë materiale interesante? Na mbështetni duke bërë një porosi ose duke na rekomanduar njohurive tuaj, , një analog unik i serverëve entry-level, i ndërtuar për ju: (disponohen variante me RAID1 dhe RAID10, deri në 24 bërthama dhe deri në 40GB DDR4).
Dell R730xd dyfish mĂ« i lirĂ« nĂ« qendrĂ«n e tĂ« dhĂ«nave Equinix Tier IV nĂ« Amsterdam? VetĂ«m kĂ«tu nĂ« HolandĂ«! Dell R420 â 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB â nga $99! Lexoni rreth
Burimi: habr.com
