Gondosan gondolja át a Docker in-Docker for CI vagy tesztkörnyezet használatát

Gondosan gondolja át a Docker in-Docker for CI vagy tesztkörnyezet használatát

A Docker-in-Docker egy virtualizált Docker-démonkörnyezet, amely magában a tárolóban fut a tárolóképek létrehozásához. A Docker-in-Docker létrehozásának fő célja magának a Dockernek a fejlesztése volt. Sokan használják a Jenkins CI futtatására. Ez elsőre normálisnak tűnik, de aztán olyan problémák merülnek fel, amelyek elkerülhetők, ha a Dockert Jenkins CI tárolóba telepítik. Ez a cikk megmondja, hogyan kell ezt megtenni. Ha érdekli a részletek nélküli végső megoldás, csak olvassa el a cikk utolsó részét, „A probléma megoldása”.

Gondosan gondolja át a Docker in-Docker for CI vagy tesztkörnyezet használatát

Docker-in-Docker: "Jó"

Több mint két éve bekerültem a Dockerbe zászló –kiváltságos és írt a dind első verziója. A cél az volt, hogy segítsék az alapcsapatot a Docker gyorsabb fejlesztésében. A Docker-in-Docker előtt a tipikus fejlesztési ciklus így nézett ki:

  • hackity hack;
  • épít;
  • egy futó Docker démon leállítása;
  • új Docker démon elindítása;
  • tesztelése;
  • ismételje meg a ciklust.

Ha gyönyörű, reprodukálható összeállítást akart készíteni (vagyis konténerben), akkor bonyolultabb lett:

  • hackity hack;
  • győződjön meg arról, hogy a Docker működő verziója fut;
  • építsen új Dockert a régi Dockerrel;
  • Docker démon leállítása;
  • indítson el egy új Docker démont;
  • teszt;
  • új Docker démon leállítása;
  • ismétlés.

A Docker-in-Docker megjelenésével a folyamat egyszerűbbé vált:

  • hackity hack;
  • összeszerelés + indítás egy szakaszban;
  • ismételje meg a ciklust.

Nem sokkal jobb így?

Gondosan gondolja át a Docker in-Docker for CI vagy tesztkörnyezet használatát

Docker-in-Docker: "Rossz"

A közhiedelemmel ellentétben azonban a Docker-in-Docker nem 100%-ban sztárok, pónik és unikornisok. Arra gondolok, hogy a fejlesztőnek több problémával tisztában kell lennie.

Az egyik az LSM-ekre (Linux biztonsági modulokra) vonatkozik, mint például az AppArmor és a SELinux: konténer futtatásakor a „belső Docker” megpróbálhat olyan biztonsági profilokat alkalmazni, amelyek ütköznek vagy összezavarják a „külső Dockert”. Ez a legnehezebben megoldható probléma a –privileged flag eredeti megvalósításának egyesítésekor. A módosításaim működtek, és minden teszt átment a Debian gépemen és az Ubuntu teszt virtuális gépeimen, de összeomlottak és kiégtek Michael Crosby gépén (ahogy emlékszem, Fedora volt neki). Nem emlékszem a probléma pontos okára, de lehet, hogy Mike egy bölcs fickó, aki SELINUX=enforce-szal dolgozik (én AppArmort használtam), és a változtatásaim nem vették figyelembe a SELinux profilokat.

Docker-in-Docker: "Gonosz"

A második probléma a Docker tároló-illesztőprogramokkal kapcsolatos. A Docker-in-Docker futtatásakor a külső Docker egy normál fájlrendszeren (EXT4, BTRFS vagy bármi más), a belső Docker pedig egy írásra másolási rendszeren (AUFS, BTRFS, Device Mapper) fut. stb.). , attól függően, hogy mi van konfigurálva külső Docker használatára). Ez sok olyan kombinációt hoz létre, amelyek nem működnek. Például nem tudja futtatni az AUFS-t az AUFS-en felül.

Ha a BTRFS-t a BTRFS-en felül futtatja, akkor először működnie kell, de ha vannak beágyazott alkötetek, a szülő alkötet törlése sikertelen lesz. Az Eszközleképező modulnak nincs névtere, így ha több Docker-példány futtatja ugyanazon a gépen, akkor mindegyik képes lesz látni (és befolyásolni) a képeket egymáson és a tároló biztonsági mentési eszközein. Ez rossz.

Sok ilyen probléma megoldására létezik megoldás. Például, ha AUFS-t szeretne használni a belső Dockerben, egyszerűen alakítsa át a /var/lib/docker mappát kötetté, és minden rendben lesz. A Docker hozzáadott néhány alapnévteret az Eszközleképező célneveihez, így ha több Docker-hívás fut ugyanazon a gépen, akkor nem lépnek egymásra.

Ez a beállítás azonban egyáltalán nem egyszerű, amint az ezekből is látszik cikkek a GitHubon található dind adattárban.

Docker-in-Docker: Egyre rosszabb

Mi a helyzet a build gyorsítótárral? Ez is elég nehéz lehet. Az emberek gyakran kérdezik tőlem, hogy „ha a Docker-in-Dockert futtatom, hogyan használhatom a gazdagépemen tárolt képeket ahelyett, hogy mindent visszahúznék a belső Dockerembe”?

Néhány vállalkozó szellemű ember megpróbálta a /var/lib/docker fájlt a gazdagépről egy Docker-in-Docker tárolóhoz kötni. Néha több tárolóval is megosztják a /var/lib/docker fájlt.

Gondosan gondolja át a Docker in-Docker for CI vagy tesztkörnyezet használatát
Meg akarja rontani az adatait? Mert pontosan ez fogja károsítani az adatait!

A Docker démont egyértelműen úgy tervezték, hogy kizárólagos hozzáféréssel rendelkezzen a /var/lib/docker fájlhoz. Semmi más nem „érinthet meg, bökhetne vagy produkálhat” az ebben a mappában található Docker-fájlokhoz.

Miért van ez így? Mert ez a dotCloud fejlesztése során levont egyik legnehezebb leckének az eredménye. A dotCloud konténermotor úgy futott, hogy egyszerre több folyamat is elérte a /var/lib/dotcloud fájlt. Az olyan furfangos trükkök, mint például az atomfájl cseréje (helyi szerkesztés helyett), a kódok figyelmeztető és kötelező zárolásokkal történő kiegészítése, valamint a biztonságos rendszerekkel, például az SQLite-tel és a BDB-vel végzett egyéb kísérletek nem mindig működtek. Amikor újraterveztük konténermotorunkat, amelyből végül Docker lett, az egyik nagy tervezési döntés az volt, hogy az összes konténerműveletet egyetlen démon alá vonjuk össze, hogy megszüntessük az összes párhuzamosítási hülyeséget.

Félreértés ne essék: teljesen lehetséges valami jót, megbízhatót és gyorsat készíteni, amely több folyamatot és modern párhuzamos vezérlést foglal magában. De úgy gondoljuk, hogy egyszerűbb és könnyebb kódot írni és karbantartani, ha a Dockert használja egyedüli lejátszóként.

Ez azt jelenti, hogy ha megosztja a /var/lib/docker könyvtárat több Docker-példány között, akkor problémái lesznek. Természetesen ez működhet, különösen a tesztelés korai szakaszában. – Figyelj, anya, én dokkolóként futtathatom az ubuntut! De próbáljon meg valami bonyolultabbat, például húzza ki ugyanazt a képet két különböző példányból, és látni fogja, hogy a világ égni fog.

Ez azt jelenti, hogy ha a CI-rendszere összeállításokat és újraépítéseket hajt végre, minden alkalommal, amikor újraindítja a Docker-in-Docker tárolót, fennáll annak a veszélye, hogy egy atommagot dob ​​a gyorsítótárába. Ez egyáltalán nem menő!

Az oldat

Tegyünk egy lépést hátra. Valóban szüksége van a Docker-in-Dockerre, vagy csak azt szeretné, hogy a Docker futtasson, és konténereket és képeket készítsen és futtasson CI-rendszeréből, miközben maga a CI-rendszer egy tárolóban van?

Fogadok, hogy a legtöbb ember az utóbbi lehetőséget szeretné, vagyis azt akarják, hogy egy olyan CI rendszer, mint a Jenkins, képes legyen konténerek futtatására. Ennek a legegyszerűbb módja, ha egyszerűen behelyez egy Docker-aljzatot a CI-tárolóba, és társítja a -v jelzővel.

Egyszerűen fogalmazva, amikor futtatja a CI-tárolót (Jenkins vagy más), ahelyett, hogy feltörne valamit a Docker-in-Dockerrel, kezdje a következő sorral:

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

Ez a tároló mostantól hozzá fog férni a Docker foglalathoz, és így képes lesz tárolók futtatására. Kivéve, hogy ahelyett, hogy „gyermek” tárolókat futtatna, „testvér” tárolókat indít el.

Próbálja ki ezt a hivatalos docker kép segítségével (amely tartalmazza a Docker bináris fájlt):

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

Úgy néz ki, és úgy működik, mint a Docker-in-Docker, de nem a Docker-in-Docker: amikor ez a tároló további tárolókat hoz létre, azok a legfelső szintű Dockerben jönnek létre. Nem fogja tapasztalni a beágyazás mellékhatásait, és az összeállítási gyorsítótár több hívás között meg lesz osztva.

Megjegyzés: A cikk korábbi verziói azt javasolták, hogy a Docker-binárist a gazdagépről a tárolóhoz kapcsolják. Ez mára megbízhatatlanná vált, mivel a Docker-motor már nem fedi le a statikus vagy csaknem statikus könyvtárakat.

Tehát, ha a Jenkins CI Docker-jét szeretné használni, két lehetősége van:
a Docker parancssori felület telepítése az alapképcsomag-rendszerrel (azaz ha a kép Debian-on alapul, használjon .deb csomagokat), a Docker API használatával.

Néhány hirdetés 🙂

Köszönjük, hogy velünk tartott. Tetszenek cikkeink? További érdekes tartalmakat szeretne látni? Támogass minket rendeléssel vagy ajánlj ismerőseidnek, felhő VPS fejlesztőknek 4.99 dollártól, a belépő szintű szerverek egyedülálló analógja, amelyet mi találtunk ki Önnek: A teljes igazság a VPS-ről (KVM) E5-2697 v3 (6 mag) 10 GB DDR4 480 GB SSD 1 Gbps 19 dollártól, vagy hogyan oszthat meg egy szervert? (RAID1 és RAID10, akár 24 maggal és akár 40 GB DDR4-gyel is elérhető).

A Dell R730xd kétszer olcsóbb az amszterdami Equinix Tier IV adatközpontban? Csak itt 2x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6 GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV 199 dollártól Hollandiában! Dell R420 - 2x E5-2430 2.2 Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 dollártól! Olvasni valamiről Hogyan építsünk infrastrukturális vállalatot? osztályú Dell R730xd E5-2650 v4 szerverek használatával 9000 eurót ér egy fillérért?

Forrás: will.com

Hozzászólás