Docker-in-Docker is 'n gevirtualiseerde Docker daemon-omgewing wat binne die houer self loop om houerbeelde te bou. Die hoofdoel van die skep van Docker-in-Docker was om Docker self te help ontwikkel. Baie mense gebruik dit om Jenkins CI te bestuur. Dit lyk aanvanklik normaal, maar dan ontstaan probleme wat vermy kan word deur Docker in 'n Jenkins CI-houer te installeer. Hierdie artikel vertel jou hoe om dit te doen. As jy belangstel in die finale oplossing sonder besonderhede, lees net die laaste afdeling van die artikel, "Die oplossing van die probleem."
Docker-in-Docker: "Goed"
Meer as twee jaar gelede het ek in Docker gesit
- hackity hack;
- bou;
- stop 'n lopende Docker-demoon;
- die bekendstelling van 'n nuwe Docker-demon;
- toets;
- herhaal die siklus.
As jy 'n pragtige, reproduceerbare samestelling (dit wil sê in 'n houer) wou maak, dan het dit meer ingewikkeld geword:
- hackity hack;
- maak seker dat 'n werkende weergawe van Docker loop;
- bou nuwe Docker met ou Docker;
- stop Docker daemon;
- begin 'n nuwe Docker-demon;
- toets;
- stop nuwe Docker daemon;
- herhaal.
Met die koms van Docker-in-Docker het die proses eenvoudiger geword:
- hackity hack;
- samestelling + lansering in een stadium;
- herhaal die siklus.
Is dit nie baie beter op hierdie manier nie?
Docker-in-Docker: "Sleg"
In teenstelling met die algemene opvatting, is Docker-in-Docker egter nie 100% sterre, ponies en eenhorings nie. Wat ek bedoel is dat daar verskeie kwessies is waarvan 'n ontwikkelaar bewus moet wees.
Een daarvan het betrekking op LSM'e (Linux-sekuriteitsmodules) soos AppArmor en SELinux: wanneer 'n houer bestuur word, kan die "interne Docker" probeer om sekuriteitsprofiele toe te pas wat die "eksterne Docker" sal konflik of verwar. Dit is die moeilikste probleem om op te los wanneer jy probeer om die oorspronklike implementering van die –bevoorregte vlag saam te voeg. My veranderinge het gewerk en alle toetse sou op my Debian-masjien en Ubuntu-toets-VM's slaag, maar hulle het op Michael Crosby se masjien neergestort en gebrand (hy het Fedora gehad soos ek onthou). Ek kan nie die presiese oorsaak van die probleem onthou nie, maar dit was dalk omdat Mike 'n wyse ou is wat met SELINUX=enforce werk (ek het AppArmor gebruik) en my veranderinge het nie SELinux-profiele in ag geneem nie.
Docker-in-Docker: "Evil"
Die tweede probleem is met Docker-bergingsbestuurders. Wanneer jy Docker-in-Docker hardloop, loop eksterne Docker bo-op 'n gewone lêerstelsel (EXT4, BTRFS, of wat jy ook al het) en interne Docker loop bo-op 'n kopieer-op-skryf-stelsel (AUFS, BTRFS, Device Mapper) , ens.). , afhangende van wat opgestel is om eksterne Docker te gebruik). Dit skep baie kombinasies wat nie sal werk nie. Byvoorbeeld, jy sal nie AUFS bo-op AUFS kan laat loop nie.
As jy BTRFS bo-op BTRFS hardloop, behoort dit eers te werk, maar sodra daar geneste subvolumes is, sal die uitvee van die ouersubvolume misluk. Die Device Mapper-module het geen naamspasie nie, so as verskeie Docker-instansies dit op dieselfde masjien laat loop, sal hulle almal die beelde op mekaar en op die houer-rugsteuntoestelle kan sien (en beïnvloed). Dit is sleg.
Daar is oplossings om baie van hierdie probleme op te los. Byvoorbeeld, as u AUFS in interne Docker wil gebruik, verander net die /var/lib/docker-lêergids in 'n volume en dit sal goed wees. Docker het 'n paar basisnaamruimtes by Device Mapper-teikenname gevoeg sodat as verskeie Docker-oproepe op dieselfde masjien loop, hulle nie op mekaar sal trap nie.
Sulke opstelling is egter glad nie eenvoudig nie, soos hieruit gesien kan word
Docker-in-Docker: Dit word erger
Wat van die boukas? Dit kan ook nogal moeilik wees. Mense vra my dikwels "as ek Docker-in-Docker gebruik, hoe kan ek beelde gebruik wat op my gasheer gehuisves word in plaas daarvan om alles terug te trek na my interne Docker"?
Sommige ondernemende mense het probeer om /var/lib/docker van die gasheer aan 'n Docker-in-Docker-houer te bind. Soms deel hulle /var/lib/docker met verskeie houers.
Wil jy jou data korrupteer? Want dit is presies wat jou data sal beskadig!
Die Docker-demoon is duidelik ontwerp om eksklusiewe toegang tot /var/lib/docker te hê. Niks anders moet enige Docker-lêers wat in hierdie vouer geleë is "aanraak, steek of prod" nie.
Hoekom is dit so? Omdat dit die resultaat is van een van die moeilikste lesse wat geleer is tydens die ontwikkeling van dotCloud. Die dotCloud-houer-enjin het gehardloop deur verskeie prosesse te hê wat gelyktydig toegang tot /var/lib/dotcloud het. Slinkse truuks soos atoomlêervervanging (in plaas van in-plek redigering), deurdringende kode met raadgewende en verpligte slotte, en ander eksperimente met veilige stelsels soos SQLite en BDB het nie altyd gewerk nie. Toe ons ons houer-enjin herontwerp het, wat uiteindelik Docker geword het, was een van die groot ontwerpbesluite om alle houerbedrywighede onder 'n enkele daemoon te konsolideer om weg te doen met al die gelyktydige nonsens.
Moet my nie verkeerd verstaan nie: dit is heeltemal moontlik om iets goed, betroubaar en vinnig te maak wat veelvuldige prosesse en moderne parallelle beheer behels. Maar ons dink dit is eenvoudiger en makliker om kode te skryf en in stand te hou met Docker as die enigste speler.
Dit beteken dat as u die /var/lib/docker-gids tussen verskeie Docker-gevalle deel, u probleme sal hê. Natuurlik kan dit werk, veral in die vroeë stadiums van toetsing. "Luister, Ma, ek kan ubuntu as 'n dokwerker bestuur!" Maar probeer iets meer kompleks, soos om dieselfde beeld uit twee verskillende gevalle te trek, en jy sal sien hoe die wêreld brand.
Dit beteken dat as jou CI-stelsel bouwerk en herbou uitvoer, elke keer as jy jou Docker-in-Docker-houer herbegin, jy die risiko loop om 'n nuke in sy kas te laat val. Dit is glad nie cool nie!
Die oplossing
Kom ons gee 'n tree terug. Het jy regtig Docker-in-Docker nodig of wil jy net Docker kan laat loop en houers en beelde vanaf jou CI-stelsel bou en laat loop terwyl daardie CI-stelsel self in 'n houer is?
Ek wed dat die meeste mense laasgenoemde opsie wil hê, wat beteken dat hulle 'n CI-stelsel soos Jenkins wil hê om houers te laat loop. En die maklikste manier om dit te doen, is om eenvoudig 'n Docker-sok in jou CI-houer te plaas en dit met die -v-vlag te assosieer.
Eenvoudig gestel, wanneer jy jou CI-houer (Jenkins of ander) bestuur, in plaas daarvan om iets saam met Docker-in-Docker te hack, begin dit met die lyn:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
Hierdie houer sal nou toegang tot die Docker-sok hê en dus houers kan laat loop. Behalwe dat in plaas daarvan om "kind"-houers te laat loop, dit "broer-houers" sal begin.
Probeer dit met die amptelike docker-beeld (wat die Docker-binêre bevat):
docker run -v /var/run/docker.sock:/var/run/docker.sock
-ti docker
Dit lyk en werk soos Docker-in-Docker, maar dit is nie Docker-in-Docker nie: wanneer hierdie houer bykomende houers skep, sal hulle in die topvlak Docker geskep word. Jy sal nie die newe-effekte van nes ervaar nie en die samestellingkas sal oor verskeie oproepe gedeel word.
Let wel: Vorige weergawes van hierdie artikel het aangeraai om die Docker-binêre van die gasheer na die houer te koppel. Dit het nou onbetroubaar geword aangesien die Docker-enjin nie meer statiese of byna statiese biblioteke dek nie.
Dus, as u Docker van Jenkins CI wil gebruik, het u 2 opsies:
die installering van die Docker CLI met behulp van die basiese beeldverpakkingstelsel (d.w.s. as jou beeld op Debian gebaseer is, gebruik .deb-pakkette), met behulp van die Docker API.
Sommige advertensies 🙂
Dankie dat jy by ons gebly het. Hou jy van ons artikels? Wil jy meer interessante inhoud sien? Ondersteun ons deur 'n bestelling te plaas of by vriende aan te beveel,
Dell R730xd 2x goedkoper in Equinix Tier IV-datasentrum in Amsterdam? Net hier
Bron: will.com