Mendoni me kujdes përpara se të përdorni Docker-in-Docker për CI ose mjedis testimi

Mendoni me kujdes përpara se të përdorni Docker-in-Docker për CI ose mjedis testimi

Docker-in-Docker është një mjedis daemon i virtualizuar i Docker që funksionon brenda vetë kontejnerit për të ndërtuar imazhe 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. Kjo duket normale në fillim, por më pas lindin probleme që mund të shmangen duke instaluar Docker në një kontejner Jenkins CI. Ky artikull ju tregon se si ta bëni këtë. Nëse jeni të interesuar për zgjidhjen përfundimtare pa detaje, thjesht lexoni pjesën e fundit të artikullit, "Zgjidhja e problemit".

Mendoni me kujdes përpara se të përdorni Docker-in-Docker për CI ose mjedis testimi

Docker-in-Docker: "Mirë"

Më shumë se dy vjet më parë futa në Docker flamur – privilegjuar dhe shkroi versioni i parë i dind. Qëllimi ishte të ndihmonte ekipin kryesor të zhvillonte Docker më shpejt. Përpara Docker-in-Docker, cikli tipik i zhvillimit dukej kështu:

  • hackity hack;
  • ndërtoj;
  • ndalimi i një demoni Docker që funksionon;
  • lëshimi i një daemon të ri Docker;
  • testimi;
  • përsërisni ciklin.

Nëse dëshironi të bëni një asamble të bukur, të riprodhueshme (d.m.th., në një enë), atëherë ajo u bë më e ndërlikuar:

  • hackity hack;
  • sigurohuni që një version funksional i Docker është duke u ekzekutuar;
  • ndërtoni Docker të ri me Docker të vjetër;
  • stop Docker daemon;
  • filloni një daemon të ri Docker;
  • test;
  • ndaloni demonin e ri Docker;
  • përsëritni.

Me ardhjen e Docker-in-Docker, procesi është bërë më i thjeshtë:

  • hackity hack;
  • montimi + nisja në një fazë;
  • përsërisni ciklin.

A nuk është shumë më mirë në këtë mënyrë?

Mendoni me kujdes përpara se të përdorni Docker-in-Docker për CI ose mjedis testimi

Docker-in-Docker: "E keqe"

Sidoqoftë, në kundërshtim me besimin popullor, Docker-in-Docker nuk është 100% yje, poni dhe njëbrirësh. Ajo që dua të them është se ka disa çështje për të cilat një zhvillues duhet të jetë i vetëdijshëm.

Një prej tyre ka të bëjë me LSM-të (modulet e sigurisë Linux) si AppArmor dhe SELinux: kur drejton një kontejner, "Docker i brendshëm" mund të përpiqet të aplikojë profile sigurie që do të konfliktojnë ose ngatërrojnë "Docker-in e jashtëm". Ky është problemi më i vështirë për t'u zgjidhur kur përpiqeni të bashkoni zbatimin origjinal të flamurit të privilegjuar. Ndryshimet e mia funksionuan dhe të gjitha testet do të kalonin në makinën time Debian dhe VM-të e testimit të Ubuntu, por ato do të përplaseshin dhe do të digjen në makinën e Michael Crosby (ai kishte Fedora siç më kujtohet). Nuk e mbaj mend shkakun e saktë të problemit, por mund të ketë qenë sepse Majk është një djalë i mençur që punon me SELINUX=enforce (kam përdorur AppArmor) dhe ndryshimet e mia nuk kanë marrë parasysh profilet SELinux.

Docker-in-Docker: "E keqe"

Problemi i dytë është me drejtuesit e ruajtjes Docker. Kur ekzekutoni Docker-in-Docker, Docker i jashtëm funksionon në krye të një sistemi skedari të rregullt (EXT4, BTRFS ose çfarëdo që keni) dhe Docker i brendshëm funksionon në krye të një sistemi kopjimi në shkrim (AUFS, BTRFS, Device Mapper , etj.), në varësi të asaj që është konfiguruar për të përdorur Docker të jashtëm). Kjo krijon shumë kombinime që nuk do të funksionojnë. Për shembull, nuk do të jeni në gjendje të ekzekutoni AUFS në krye të AUFS.

Nëse përdorni BTRFS në krye të BTRFS, ai duhet të funksionojë në fillim, por pasi të ketë nënvëllime të ndërlidhura, fshirja e nënvëllimit prind do të dështojë. Moduli Device Mapper nuk ka hapësirë ​​emri, kështu që nëse disa raste të Docker e përdorin atë në të njëjtën makinë, të gjithë do të jenë në gjendje të shohin (dhe të ndikojnë) imazhet në njëri-tjetrin dhe në pajisjet rezervë të kontejnerit. Kjo është e keqe.

Ka zgjidhje për të zgjidhur shumë nga këto probleme. Për shembull, nëse doni të përdorni AUFS në Docker të brendshëm, thjesht kthejeni dosjen /var/lib/docker në një vëllim dhe do të jeni mirë. Docker ka shtuar disa hapësira emrash bazë në emrat e synimeve të Device Mapper në mënyrë që nëse thirrjet e shumta Docker janë duke u ekzekutuar në të njëjtën makinë, ato të mos shkelin njëri-tjetrin.

Sidoqoftë, një konfigurim i tillë nuk është aspak i thjeshtë, siç mund të shihet nga këto artikuj në depon e dind në GitHub.

Docker-in-Docker: Përkeqësohet

Po në lidhje me cache-in e ndërtimit? Kjo gjithashtu mund të jetë mjaft e vështirë. Njerëzit shpesh më pyesin "nëse jam duke ekzekutuar Docker-in-Docker, si mund të përdor imazhet e vendosura në hostin tim në vend që të tërheq gjithçka përsëri në Docker-in tim të brendshëm"?

Disa njerëz iniciativë janë përpjekur të lidhin /var/lib/docker nga hosti në një kontejner Docker-in-Docker. Ndonjëherë ata ndajnë /var/lib/docker me kontejnerë të shumtë.

Mendoni me kujdes përpara se të përdorni Docker-in-Docker për CI ose mjedis testimi
Dëshironi të korruptoni të dhënat tuaja? Sepse kjo është pikërisht ajo që do të dëmtojë të dhënat tuaja!

Daemon Docker ishte krijuar qartë për të pasur akses ekskluziv në /var/lib/docker. Asgjë tjetër nuk duhet të "prek, shtyjë ose nxisë" ndonjë skedar Docker të vendosur në këtë dosje.

Pse është kështu? Sepse ky është rezultat i një prej mësimeve më të vështira të nxjerra gjatë zhvillimit të dotCloud. Motori i kontejnerit dotCloud funksionoi duke pasur procese të shumta që aksesonin /var/lib/dotcloud njëkohësisht. Truket dinake si zëvendësimi i skedarit atomik (në vend të redaktimit në vend), shtimi i kodit me bllokime këshilluese dhe të detyrueshme dhe eksperimente të tjera me sisteme të sigurta si SQLite dhe BDB nuk funksionuan gjithmonë. Kur po ridizajnonim motorin tonë të kontejnerëve, i cili përfundimisht u bë Docker, një nga vendimet e mëdha të projektimit ishte konsolidimi i të gjitha operacioneve të kontejnerëve nën një demon të vetëm për të hequr të gjitha marrëzitë e njëkohshme.

Mos më keqkuptoni: është plotësisht e mundur të bëhet diçka e mirë, e besueshme dhe e shpejtë që përfshin procese të shumta dhe kontroll paralel modern. Por ne mendojmë se është më e thjeshtë dhe më e lehtë për të shkruar dhe mbajtur kodin duke përdorur Docker si lojtarin e vetëm.

Kjo do të thotë që nëse ndani direktorinë /var/lib/docker midis shumë instancave të Docker, do të keni probleme. Sigurisht, kjo mund të funksionojë, veçanërisht në fazat e hershme të testimit. "Dëgjo, Mami, unë mund të drejtoj ubuntu-në si doker!" Por provoni diçka më komplekse, si tërheqja e të njëjtit imazh nga dy raste të ndryshme, dhe do të shihni se bota digjet.

Kjo do të thotë që nëse sistemi juaj CI kryen ndërtime dhe rindërtime, sa herë që rinisni kontejnerin tuaj Docker-in-Docker, rrezikoni të hidhni një armë bërthamore në cache-in e tij. Kjo nuk është aspak e lezetshme!

Zgjidhja e problemeve

Le të bëjmë një hap prapa. Keni vërtet nevojë për Docker-in-Docker apo thjesht dëshironi të jeni në gjendje të ekzekutoni Docker dhe të ndërtoni dhe ekzekutoni kontejnerë dhe imazhe nga sistemi juaj CI ndërsa vetë ai sistem CI është në një kontejner?

Vë bast se shumica e njerëzve duan opsionin e fundit, që do të thotë se ata duan që një sistem CI si Jenkins të jetë në gjendje të drejtojë kontejnerë. Dhe mënyra më e lehtë për ta bërë këtë është thjesht të futni një fole Docker në kontejnerin tuaj CI dhe ta lidhni atë me flamurin -v.

E thënë thjesht, kur përdorni kontejnerin tuaj CI (Jenkins ose tjetër), në vend që të hakoni diçka së bashku me Docker-in-Docker, filloni atë me linjën:

docker run -v /var/run/docker.sock:/var/run/docker.sock ...

Ky kontejner tani do të ketë qasje në folenë Docker dhe për këtë arsye mund të ekzekutojë kontejnerët. Me përjashtim të faktit se në vend të përdorimit të kontejnerëve "fëmijë", do të lëshojë kontejnerët "vëlla dhe motra".

Provoni këtë duke përdorur imazhin zyrtar të dokerit (i cili përmban binarin Docker):

docker run -v /var/run/docker.sock:/var/run/docker.sock 
           -ti docker

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 të nivelit të lartë. Nuk do të përjetoni efektet anësore të foleve dhe memoria e montimit do të ndahet nëpër thirrje të shumta.

Shënim: Versionet e mëparshme të këtij artikulli këshilluan lidhjen e binarit Docker nga hosti me kontejnerin. Kjo tani është bërë jo e besueshme pasi motori Docker nuk mbulon më bibliotekat statike ose pothuajse statike.

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

Disa reklama 🙂

Faleminderit që qëndruat me ne. A ju pëlqejnë artikujt tanë? Dëshironi të shihni përmbajtje më interesante? Na mbështesni duke bërë një porosi ose duke rekomanduar miqve, cloud VPS për zhvilluesit nga 4.99 dollarë, një analog unik i serverëve të nivelit të hyrjes, i cili u shpik nga ne për ju: E gjithë e vërteta rreth VPS (KVM) E5-2697 v3 (6 bërthama) 10 GB DDR4 480 GB SSD 1 Gbps nga 19 dollarë ose si të ndani një server? (e disponueshme me RAID1 dhe RAID10, deri në 24 bërthama dhe deri në 40 GB DDR4).

Dell R730xd 2 herë më lirë në qendrën e të dhënave Equinix Tier IV në Amsterdam? Vetëm këtu 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV nga 199$ në Holandë! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - nga 99 dollarë! Lexoni rreth Si të ndërtohet korporata e infrastrukturës. klasë me përdorimin e serverëve Dell R730xd E5-2650 v4 me vlerë 9000 euro për një qindarkë?

Burimi: www.habr.com

Shto një koment