Harkitse huolellisesti, ennen kuin käytät Docker in-Docker for CI:tä tai testiympäristöä

Harkitse huolellisesti, ennen kuin käytät Docker in-Docker for CI:tä tai testiympäristöä

Docker-in-Docker on virtualisoitu Docker-daemon-ympäristö, joka toimii itse säilössä konttikuvien luomiseksi. Docker-in-Dockerin luomisen päätarkoitus oli auttaa kehittämään itse Dockeria. Monet ihmiset käyttävät sitä Jenkins CI:n ajamiseen. Tämä vaikuttaa aluksi normaalilta, mutta sitten syntyy ongelmia, jotka voidaan välttää asentamalla Docker Jenkins CI -säilöön. Tässä artikkelissa kerrotaan, kuinka tämä tehdään. Jos olet kiinnostunut lopullisesta ratkaisusta ilman yksityiskohtia, lue artikkelin viimeinen osa "Ongelman ratkaiseminen".

Harkitse huolellisesti, ennen kuin käytät Docker in-Docker for CI:tä tai testiympäristöä

Docker-in-Docker: "Hyvä"

Yli kaksi vuotta sitten siirryin Dockeriin lippu – etuoikeutettu ja kirjoitti dindin ensimmäinen versio. Tavoitteena oli auttaa ydintiimiä kehittämään Dockeria nopeammin. Ennen Docker-in-Dockeria tyypillinen kehityssykli näytti tältä:

  • hakkerointi hakkerointi;
  • rakentaa;
  • käynnissä olevan Docker-daemonin pysäyttäminen;
  • uuden Docker-daemonin käynnistäminen;
  • testaus;
  • toista sykli.

Jos halusit tehdä kauniin, toistettavan kokoonpanon (eli säiliössä), siitä tuli monimutkaisempi:

  • hakkerointi hakkerointi;
  • varmista, että Dockerin toimiva versio on käynnissä;
  • rakentaa uusi Docker vanhan Dockerin kanssa;
  • pysäyttää Docker-daemon;
  • käynnistä uusi Docker-daemon;
  • testata;
  • pysäyttää uusi Docker-daemon;
  • toistaa.

Docker-in-Dockerin myötä prosessi on yksinkertaistunut:

  • hakkerointi hakkerointi;
  • kokoonpano + käynnistäminen yhdessä vaiheessa;
  • toista sykli.

Eikö se ole paljon parempi näin?

Harkitse huolellisesti, ennen kuin käytät Docker in-Docker for CI:tä tai testiympäristöä

Docker-in-Docker: "Huono"

Toisin kuin yleisesti uskotaan, Docker-in-Docker ei kuitenkaan ole 100 % tähtiä, poneja ja yksisarvisia. Tarkoitan sitä, että kehittäjän on oltava tietoinen useista seikoista.

Yksi niistä koskee LSM:itä (Linux-suojausmoduuleja), kuten AppArmor ja SELinux: konttia ajaessaan "sisäinen Docker" voi yrittää käyttää suojausprofiileja, jotka ovat ristiriidassa "ulkoisen Dockerin" kanssa tai sekoittavat sen. Tämä on vaikein ratkaistava ongelma yritettäessä yhdistää etuoikeutetun lipun alkuperäinen toteutus. Muutokseni toimi ja kaikki testit läpäisivät Debian-koneeni ja Ubuntu-testi-VM:ni, mutta ne kaatuivat ja polttivat Michael Crosbyn koneella (hänellä oli muistaakseni Fedora). En muista tarkkaa ongelman syytä, mutta se saattoi johtua siitä, että Mike on viisas kaveri, joka työskentelee SELINUX=enforcen kanssa (käytin AppArmoria) ja muutokseni eivät huomioineet SELinux-profiileja.

Docker-in-Docker: "Paha"

Toinen ongelma liittyy Dockerin tallennusajureihin. Kun suoritat Docker-in-Doceria, ulkoinen Docker toimii tavallisen tiedostojärjestelmän (EXT4, BTRFS tai mikä tahansa sinulla) päällä ja sisäinen Docker toimii kopiointi-kirjoitusjärjestelmän (AUFS, BTRFS, Device Mapper) päällä. jne.) riippuen siitä, mikä on määritetty käyttämään ulkoista Dockeria). Tämä luo monia yhdistelmiä, jotka eivät toimi. Et esimerkiksi voi suorittaa AUFS:ää AUFS:n päällä.

Jos käytät BTRFS:ää BTRFS:n päällä, sen pitäisi toimia aluksi, mutta kun sisäkkäisiä alitaltioita on, yläalitaltion poistaminen epäonnistuu. Device Mapper -moduulilla ei ole nimiavaruutta, joten jos useat Docker-instanssit käyttävät sitä samassa koneessa, ne kaikki voivat nähdä (ja vaikuttaa) kuvat toisiinsa ja säilön varmuuskopiointilaitteisiin. Tämä on huono.

On olemassa kiertotapoja monien näiden ongelmien ratkaisemiseksi. Jos esimerkiksi haluat käyttää AUFS:ää sisäisessä Dockerissa, käännä /var/lib/docker-kansio taltioksi, niin kaikki on kunnossa. Docker on lisännyt joitain perusnimiavaruuksia Device Mapperin kohdenimiin, jotta jos useita Docker-kutsuja on käynnissä samassa koneessa, ne eivät astu päällekkäin.

Tällainen asennus ei kuitenkaan ole ollenkaan yksinkertainen, kuten näistä voidaan nähdä artikkelit GitHubin dind-varastossa.

Docker-in-Docker: Se pahenee

Entä rakennusvälimuisti? Tämä voi olla myös melko vaikeaa. Ihmiset kysyvät minulta usein "jos käytän Docker-in-Dockeria, kuinka voin käyttää isännässäni olevia kuvia sen sijaan, että vedän kaiken takaisin sisäiseen Dockeriini"?

Jotkut yritteliäät ihmiset ovat yrittäneet sitoa /var/lib/docker-tiedoston isännästä Docker-in-Docker-säilöön. Joskus ne jakavat /var/lib/docker useiden säilöjen kanssa.

Harkitse huolellisesti, ennen kuin käytät Docker in-Docker for CI:tä tai testiympäristöä
Haluatko turmella tietosi? Koska tämä on juuri se, mikä vahingoittaa tietojasi!

Docker-daemon oli selkeästi suunniteltu siten, että sillä on yksinomainen pääsy tiedostoon /var/lib/docker. Mikään muu ei saa "koskea, pistää tai tuottaa" tässä kansiossa olevia Docker-tiedostoja.

Miksi näin on? Koska tämä on tulos yhdestä vaikeimmista dotCloudia kehitettäessä. DotCloud-konttimoottoria käytettiin useilla prosesseilla, jotka käyttivät /var/lib/dotcloudia samanaikaisesti. Ovelat temput, kuten atomitiedostojen korvaaminen (paikan päällä tapahtuvan muokkauksen sijaan), koodin lisääminen neuvoa-antavilla ja pakollisilla lukoilla ja muut kokeet suojatuilla järjestelmillä, kuten SQLite ja BDB, eivät aina toimineet. Kun suunnittelimme uudelleen konttimoottoriamme, josta lopulta tuli Docker, yksi suurimmista suunnittelupäätöksistä oli yhdistää kaikki konttitoiminnot yhden demonin alle, jotta kaikki samanaikaisuuden hölynpölyt saadaan pois.

Älä ymmärrä minua väärin: on täysin mahdollista tehdä jotain hyvää, luotettavaa ja nopeaa, joka sisältää useita prosesseja ja modernia rinnakkaisohjausta. Mutta mielestämme on yksinkertaisempaa ja helpompaa kirjoittaa ja ylläpitää koodia käyttämällä Dockeria ainoana soittimena.

Tämä tarkoittaa, että jos jaat /var/lib/docker-hakemiston useiden Docker-instanssien kesken, sinulla on ongelmia. Tämä voi tietysti toimia, varsinkin testauksen alkuvaiheessa. "Kuule, äiti, voin ajaa ubuntua telakkana!" Mutta kokeile jotain monimutkaisempaa, kuten saman kuvan ottamista kahdesta eri tapauksesta, niin näet maailman palavan.

Tämä tarkoittaa, että jos CI-järjestelmäsi suorittaa koontiosia ja uudelleenrakennuksia, joka kerta kun käynnistät Docker-in-Docker-säilösi uudelleen, voit pudottaa ydinvoimalan sen välimuistiin. Tämä ei ole ollenkaan siistiä!

Liuos

Otetaan askel taaksepäin. Tarvitsetko todella Docker-in-Dokeria vai haluatko vain pystyä ajamaan Dockeria ja rakentamaan ja ajamaan säilöjä ja kuvia CI-järjestelmästäsi, kun itse CI-järjestelmä on säilössä?

Lyön vetoa, että useimmat ihmiset haluavat jälkimmäisen vaihtoehdon, mikä tarkoittaa, että he haluavat Jenkinsin kaltaisen CI-järjestelmän pystyvän ajamaan säiliöitä. Ja helpoin tapa tehdä tämä on yksinkertaisesti työntää Docker-liitin CI-säilöön ja yhdistää se -v-lippuun.

Yksinkertaisesti sanottuna, kun käytät CI-säilöäsi (Jenkins tai muu), sen sijaan, että hakkeroit jotain yhdessä Docker-in-Dockerin kanssa, aloita se rivillä:

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

Tällä säiliöllä on nyt pääsy Docker-pistorasiaan, ja se voi siten käyttää säiliöitä. Paitsi että "lapsi"-säilöjen käyttämisen sijaan se käynnistää "sisarus"-säilöjä.

Kokeile tätä käyttämällä virallista Docker-kuvaa (joka sisältää Docker-binaarin):

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

Se näyttää ja toimii kuten Docker-in-Docker, mutta se ei ole Docker-in-Docker: kun tämä säilö luo lisäsäiliöitä, ne luodaan ylimmän tason Dockerissa. Et koe sisäkkäisyyden sivuvaikutuksia, ja kokoonpanovälimuisti jaetaan useiden puhelujen kesken.

Huomautus: Tämän artikkelin aiemmissa versioissa neuvottiin linkittämään Docker-binaari isännästä säilöön. Tästä on nyt tullut epäluotettava, koska Docker-moottori ei enää kata staattisia tai lähes staattisia kirjastoja.

Joten jos haluat käyttää Jenkins CI:n Dockeria, sinulla on kaksi vaihtoehtoa:
Dockerin CLI:n asentaminen käyttämällä peruskuvan pakkausjärjestelmää (eli jos kuvasi perustuu Debianiin, käytä .deb-paketteja) Docker API:n avulla.

Muutamia mainoksia 🙂

Kiitos, että pysyt kanssamme. Pidätkö artikkeleistamme? Haluatko nähdä mielenkiintoisempaa sisältöä? Tue meitä tekemällä tilauksen tai suosittelemalla ystäville, pilvi VPS kehittäjille alkaen 4.99 dollaria, ainutlaatuinen lähtötason palvelimien analogi, jonka me keksimme sinulle: Koko totuus VPS (KVM) E5-2697 v3 (6 ydintä) 10 Gt DDR4 480 Gt SSD 1 Gbps alkaen 19 dollarista tai kuinka jakaa palvelin? (saatavana RAID1:n ja RAID10:n kanssa, jopa 24 ydintä ja jopa 40 Gt DDR4-muistia).

Dell R730xd 2 kertaa halvempi Equinix Tier IV -palvelinkeskuksessa Amsterdamissa? Vain täällä 2 x Intel TetraDeca-Core Xeon 2 x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV alkaen 199 dollaria Alankomaissa! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - alkaen 99 dollaria! Lukea Kuinka rakentaa infrastruktuuriyritys. luokkaa Dell R730xd E5-2650 v4 -palvelimilla 9000 euron arvosta penniä vastaan?

Lähde: will.com

Lisää kommentti