Mendoni mirë përpara se të përdorni Docker-in-Docker për CI ose ambient testimi

Mendoni mirë përpara se të përdorni Docker-in-Docker për CI ose ambient testimi

Docker-in-Docker është një mjedis i virtualizuar Docker-daemon, i cili ekzekutohet brenda vetë kontejnerit për ndërtimin e imazheve të kontejnerit. Qëllimi kryesor i krijimit të Docker-in-Docker ishte të ndihmonte në zhvillimin e vetë Docker. Shumë njerëz e përdorin atë për të drejtuar Jenkins CI. Në fillim duket normale, por pastaj lindin probleme që mund të shmangen duke instaluar Docker në kontejnerin 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".

Mendoni mirë përpara se të përdorni Docker-in-Docker për CI ose ambient testimi

Docker-in-Docker: "I Mirë"

Më shumë se dy vjet më parë, unë kam vendosur në Docker --all --privileged dhe shkrova versionin e parë dind. Qëllimi ishte të ndihmonte ekipin kryesor të zhvillonte Docker më shpejt. Para se të kishte Docker-in-Docker, cikli tipik i zhvillimit ishte kështu:

  • hackity hack;
  • ndĂ«rtimi (build);
  • ndalimi i Docker-daemonit tĂ« ekzekutuar;
  • ekzekutimi i njĂ« Docker-daemoni tĂ« ri;
  • testimi;
  • riprojci; eksperimentimi.

Nëse dëshironit të bëni një ndërtim të bukur dhe të riprodhueshëm (dmth. brenda kontejnerit), atëherë bëhej më e komplikuar:

  • hackity hack;
  • tĂ« siguroheni qĂ« tĂ« keni njĂ« version funksional tĂ« Docker;
  • tĂ« ndĂ«rtosh njĂ« Docker tĂ« ri me Docker-in e vjetĂ«r;
  • ndaleni Docker-daemonin;
  • ekzekutoni njĂ« Docker-daemon tĂ« ri;
  • testoni;
  • ndaloni Docker-daemonin e ri;
  • pĂ«rsĂ«ritni.

Me ardhjen e Docker-in-Docker, procesi u thjeshtua:

  • hackity hack;
  • ndĂ«rtimi + ekzekutimi nĂ« njĂ« hap;
  • riprojci; eksperimentimi.

A nuk është kështu shumë më mirë?

Mendoni mirë përpara se të përdorni Docker-in-Docker për CI ose ambient testimi

Docker-in-Docker: "I Keq"

MegjithatĂ«, pĂ«rkundĂ«r mendimit tĂ« zakonshĂ«m, Docker-in-Docker nuk Ă«shtĂ« 100% e bĂ«rĂ« nga yje, ponies dhe njĂ«horna. Po flas pĂ«r disa probleme qĂ« zhvilluesi duhet t’i dijĂ«.

NjĂ« nga to ka tĂ« bĂ«jĂ« me LSM (modulet e sigurisĂ« Linux), si AppArmor dhe SELinux: kur nisni njĂ« kontejner, "Docker-i brendshĂ«m" mund tĂ« pĂ«rpiqet tĂ« aplikojĂ« profile sigurie qĂ« do tĂ« bien nĂ« konflikt ose do tĂ« ngatĂ«rrojnĂ« "Docker-in e jashtĂ«m". Ky Ă«shtĂ« problemi mĂ« i vĂ«shtirĂ« qĂ« duhet zgjidhur kur pĂ«rpiqeni tĂ« bashkoni implementimin origjinal tĂ« flamurit –privileged. Ndryshimet e mia funksionuan, dhe tĂ« gjitha testet do tĂ« kalonin nĂ« makinĂ«n time Debian dhe nĂ« makinat virtuale testuese Ubuntu, por do tĂ« kolapsin dhe do tĂ« digjĂ«n nĂ« makinĂ«n e Maikll Krosbit (sa mĂ« kujtohet, ai kishte Fedora). Nuk mund tĂ« kujtoj shkakun e saktĂ« tĂ« problemit, por ndoshta ndodhi sepse Maik Ă«shtĂ« njĂ« njeri i mençur, i cili punon me SELINUX=enforce (unĂ« pĂ«rdora AppArmor), dhe ndryshimet e mia nuk e merrnin parasysh profilin SELinux.

Docker-in-Docker: "E keqe"

Problemi i dytë ka të bëjë me drejtuesit e ruajtjes së Docker. Kur nisni Docker-in-Docker, Docker-i i jashtëm funksionon mbi një sistem të zakonshëm skedari (EXT4, BTRFS ose çfarëdo tjetër që keni), ndërsa Docker-i brendshëm funksionon mbi sistemin e kopjimit në shkrim (AUFS, BTRFS, Device Mapper, etj., në varësi të asaj çfarë është konfiguruar të përdoret nga Docker-i i jashtëm). Kjo sjell shumë kombinime që nuk do të funksionojnë. Për shembull, nuk do të mund të ekzekutoni AUFS mbi AUFS.

Nëse po përdorni BTRFS mbi BTRFS, fillimisht duhet të funksionojë, por sa më shumë nënkategoritë të krijohen, nuk do të mund të hiqni nënkategorinë prind parent subvolume. Moduli Device Mapper nuk ka hapësira emërtimi, prandaj, nëse disa instanca Docker-i e përdorin atë në të njëjtën makinë, të gjitha do të jenë në gjendje të shohin (dhe të ndikojnë në) imazhet e njëri-tjetrit dhe të pajisjet e kopjimit të kontejnerëve. Kjo është keq.

Ekzistojnë rrugë alternative për zgjidhjen e shumë prej këtyre problemeve. Për shembull, nëse dëshironi të përdorni AUFS në Docker-in e brendshëm, thjesht shndërroni dosjen /var/lib/docker në atë, dhe gjithçka do të jetë në rregull. Docker ka shtuar disa hapësira emërtimi bazë në emrat e synuar të Device Mapper, kështu që nëse disa thirrje Docker-i realizohen në të njëjtën makinë, ato nuk do të "shkelin" njëra-tjetrën.

Megjithatë, një konfigurim i tillë nuk është fare i lehtë, siç mund ta shihni nga këta artikull në repo dind në GitHub.

Docker-in-Docker: bëhet edhe më keq

ÇfarĂ« ndodh me cache-n e ndĂ«rtimit? Kjo gjithashtu mund tĂ« jetĂ« mjaft e komplikuar. NjerĂ«zit shpesh mĂ« pyesin, “nĂ«se po pĂ«rdor Docker-in-Docker, si mund tĂ« pĂ«rdor imazhet qĂ« ndodhen nĂ« host-in tim, pĂ«rveç se tĂ« rikthej gjithçka nĂ« Docker-in tim tĂ« brendshĂ«m”?

Disa njerëz të ndërmarrë kanë provuar të lidhin /var/lib/docker nga host-i në kontejnerin Docker-in-Docker. Ndonjëherë ata ndajnë /var/lib/docker me disa kontejnerë.

Mendoni mirë përpara se të përdorni Docker-in-Docker për CI ose ambient testimi
Doni të dëmtoni të dhënat? Sepse kjo është pikërisht ajo që do të dëmtojë të dhënat tuaja!

Docker-daemon ishte qartësisht i dizajnuar për të pasur qasje ekskluzive në /var/lib/docker. Asgjë tjetër nuk duhet "të prekë, të bëjë thirrje ose të shqetësojë" skedat e Docker-it që ndodhen në këtë dosje.

Pse është kështu? Sepse kjo është një nga mësimet më të vështira që mësuam gjatë zhvillimit të dotCloud. Motori i kontejnerëve dotCloud funksiononte me disa procese që aksesonin paralelisht /var/lib/dotcloud. Hile të tilla si zëvendësimi atomik i skedarëve (në vend të editimit në vend), "shpërndarja" e kodit me bllokime rekomanduese dhe të detyrueshme dhe eksperimente të tjera me sisteme të sigurta si SQLite dhe BDB, nuk funksiononin gjithmonë. Kur ne ri-dizajnua mekanizmin tonë të kontejnerëve, i cili përfundimisht u shndërrua në Docker, një nga vendimet kryesore të dizajnit ishte të grumbulloheshin të gjitha operacionet me kontejnerët nën një daemon të vetëm, për të përfunduar të gjithë këtë budallallëk të qasjes së përbashkët.

Mos më kuptoni gabim: është e mundur të bëni diçka të mirë, të besueshme dhe të shpejtë, që përfshin disa procese dhe menaxhim modern paralel. Por ne mendojmë se është më e thjeshtë dhe më e lehtë të shkruani dhe mbani kod duke përdorur Docker si lojtarin e vetëm.

Kjo do tĂ« thotĂ« se nĂ«se ndani katalogun /var/lib/docker midis disa instancave tĂ« Docker-it, do tĂ« keni probleme. Sigurisht, kjo mund tĂ« funksionojĂ«, veçanĂ«risht nĂ« fazat e hershme tĂ« testimit. “DĂ«gjo, mama, unĂ« mund ta nisim ubuntu me ‘docker’!” Por provoni tĂ« bĂ«ni diçka mĂ« tĂ« komplikuar, si tĂ« nxirrni tĂ« njĂ«jtin imazh nga dy instanca tĂ« krijuara ndaras dhe do tĂ« shihni si digjet bota.

Kjo do të thotë se nëse sistemi juaj CI bën ndërtesa dhe rindezje, çdo herë kur ristartoni kontejnerin Docker-in-Docker rrezikoni të riktheni në cache një bombë bërthamore. Kjo nuk është aspak e këndshme!

Zgjidhja e problemit

Le të bëjmë një hap prapa. A ju nevojitet vërtet Docker-in-Docker apo thjesht doni të keni mundësinë të drejtoni Docker, domethënë të ndërtoni dhe ekzekutoni kontejnerë dhe imazhe nga sistemi juaj CI, ndërsa vetë ky sistem CI është në një kontejner?

Beso se shumicës së njerëzve u nevojitet opsioni i fundit, do të thotë që ata duan që një sistem CI, si Jenkins, të jetë në gjendje të drejtojë kontejnerë. Dhe mënyra më e thjeshtë për ta bërë këtë është thjesht të vendosni socket-in e Docker në kontejnerin tuaj CI, duke e lidhur atë me flagun -v.

Thënë thjesht, kur të drejtoni kontejnerin tuaj CI (Jenkins ose ndonjë tjetër), në vend që të thyej diçka bashkë me 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ë akses në socket-in e Docker dhe, për pasojë, do të jetë në gjendje të drejtojë kontejnerë. Përveç se në vend të ekzekutimit të kontejnerëve "fëmijë" ai do të drejtojë kontejnerë "prindër".

Provojeni 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 docker

Kjo duket dhe funksionon si Docker-in-Docker, por nuk është Docker-in-Docker: kur ky kontejner të krijojë kontejnerë shtesë, ata do të krijohen në Dockerin e nivelit më të lartë. Nuk do të përjetoni efekte anësore të thellësisë, dhe cache i ndërtimit do të ndahet për thirrje të shumta.

Shënim: versionet e mëparshme të këtij artikulli këshillonin që të lidhni skedarin binar të Docker nga hosti në kontejner. Tani kjo është bërë e pasigurt, pasi mekanizmi i Docker nuk zgjerohet më në biblioteka statike ose pothuajse statike.

Pra, nëse dëshironi të përdorni Docker nga Jenkins CI, keni 2 opsione:
instalimi i Docker CLI duke përdorur sistemin bazë të paketimit të imazhit (dmth. nëse imazhi juaj bazohet në Debian, përdorni paketat .deb), duke përdorur API Docker.

Pak reklamĂ« 🙂

Faleminderit që po qëndroni me ne. Ju pëlqen artikujt tanë? Doni të shihni më shumë materiale interesante? Na mbështesni duke bërë një porosi ose duke rekomanduar tek miqtë tuaj, VPS cloud për zhvillues nga $4.99, një analog unik i serverëve entry-level që e kemi shpikur për Ju: E gjithë e vërteta në lidhje me VPS (KVM) E5-2697 v3 (6 Bërthama) 10GB DDR4 480GB SSD 1Gbps nga $19 ose si ta ndajmë saktësisht serverin? (opcionet me RAID1 dhe RAID10, deri në 24 bërthama dhe deri në 40GB DDR4 janë të disponueshme).

Dell R730xd dyfish mĂ« i lirĂ« nĂ« qendĂ«r tĂ« tĂ« dhĂ«nave Equinix Tier IV nĂ« Amsterdam? VetĂ«m te ne 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TB nga $199 nĂ« HolandĂ«! Dell R420 — 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB — nga $99! Lexoni rreth Si tĂ« ndĂ«rtoni njĂ« infrastrukturĂ« tĂ« klasĂ«s korporative me pĂ«rdorimin e serverĂ«ve Dell R730xd E5-2650 v4 me çmim 9000 euro pĂ«r pak para?

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster