Než použijete Docker-in-Docker pro CI nebo testovací prostředí, dvakrát si to rozmyslete

Než použijete Docker-in-Docker pro CI nebo testovací prostředí, dvakrát si to rozmyslete

Docker-in-Docker je virtualizované prostředí démona Docker běžící v samotném kontejneru za účelem vytváření obrazů kontejneru. Hlavním účelem vytvoření Docker-in-Docker bylo pomoci s vývojem samotného Dockeru. Mnoho lidí jej používá ke spuštění Jenkins CI. Zpočátku se to zdá normální, ale pak nastanou problémy, kterým se lze vyhnout instalací Dockeru do kontejneru Jenkins CI. Tento článek vám řekne, jak to udělat. Pokud vás zajímá konečné řešení bez podrobností, stačí si přečíst poslední část článku „Řešení problému“.

Než použijete Docker-in-Docker pro CI nebo testovací prostředí, dvakrát si to rozmyslete

Docker-in-Docker: "Dobré"

Před více než dvěma lety jsem vložil do Docker vlajka – privilegovaný a psal první verze dind. Cílem bylo pomoci základnímu týmu vyvinout Docker rychleji. Před Docker-in-Docker vypadal typický vývojový cyklus takto:

  • hackity hack;
  • stavět;
  • zastavení běžícího démona Docker;
  • spuštění nového démona Docker;
  • testování;
  • opakování cyklu.

Pokud jste chtěli vytvořit krásnou, reprodukovatelnou sestavu (to znamená v kontejneru), bylo to složitější:

  • hackity hack;
  • ujistěte se, že běží funkční verze Dockeru;
  • vytvořit nový Docker se starým Dockerem;
  • zastavit démona Docker;
  • spustit nového démona Docker;
  • test;
  • zastavit nového démona Docker;
  • opakovat.

S příchodem Docker-in-Docker se proces zjednodušil:

  • hackity hack;
  • montáž + spuštění v jedné fázi;
  • opakování cyklu.

Není to takhle mnohem lepší?

Než použijete Docker-in-Docker pro CI nebo testovací prostředí, dvakrát si to rozmyslete

Docker-in-Docker: "Špatný"

Na rozdíl od všeobecného přesvědčení však Docker-in-Docker nejsou 100% hvězdy, poníci a jednorožci. Chci říct, že existuje několik problémů, kterých si vývojář musí být vědom.

Jeden z nich se týká LSM (Linuxových bezpečnostních modulů), jako jsou AppArmor a SELinux: při spuštění kontejneru se může „interní Docker“ pokusit použít bezpečnostní profily, které budou v konfliktu nebo matoucí „externí Docker“. Toto je nejobtížněji řešitelný problém při pokusu o sloučení původní implementace příznaku –privileged. Moje změny fungovaly a všechny testy prošly na mém počítači Debian a testovacích virtuálních počítačích Ubuntu, ale na počítači Michaela Crosbyho (měl Fedoru, jak si vzpomínám) se zhroutily a spálily. Nepamatuji si přesnou příčinu problému, ale mohlo to být způsobeno tím, že Mike je moudrý člověk, který pracuje s SELINUX=enforce (použil jsem AppArmor) a moje změny nebraly v úvahu profily SELinux.

Docker-in-Docker: "Zlo"

Druhý problém je s ovladači úložiště Docker. Když spustíte Docker-in-Docker, externí Docker běží nad běžným souborovým systémem (EXT4, BTRFS nebo cokoli jiného) a interní Docker běží nad systémem kopírování při zápisu (AUFS, BTRFS, Device Mapper , atd.). v závislosti na tom, co je nakonfigurováno pro použití externího Dockeru). Vznikne tak mnoho kombinací, které nebudou fungovat. Například nebudete moci spouštět AUFS nad AUFS.

Pokud spustíte BTRFS nad BTRFS, mělo by to zpočátku fungovat, ale jakmile budou vnořené podsvazky, odstranění nadřazeného podsvazku se nezdaří. Modul Device Mapper nemá žádný jmenný prostor, takže pokud jej na stejném počítači provozuje více instancí Dockeru, všechny budou moci vidět (a ovlivňovat) obrazy na sobě navzájem a na zařízeních pro zálohování kontejnerů. Je to špatné.

Mnoho z těchto problémů lze vyřešit. Pokud chcete například používat AUFS v interním Dockeru, stačí přeměnit složku /var/lib/docker na svazek a budete v pořádku. Docker přidal některé základní jmenné prostory k cílovým názvům Device Mapper, takže pokud na stejném počítači běží více volání Dockeru, nebudou na sebe šlapat.

Takové nastavení však není vůbec jednoduché, jak je z nich patrné články v úložišti Dind na GitHubu.

Docker-in-Docker: Zhoršuje se to

A co mezipaměť sestavení? To může být také docela obtížné. Lidé se mě často ptají: „Pokud používám Docker-in-Docker, jak mohu použít obrázky hostované na mém hostiteli namísto stahování všeho zpět do mého interního Dockeru“?

Někteří podnikaví lidé se pokusili svázat /var/lib/docker z hostitele s kontejnerem Docker-in-Docker. Někdy sdílejí /var/lib/docker s více kontejnery.

Než použijete Docker-in-Docker pro CI nebo testovací prostředí, dvakrát si to rozmyslete
Chcete poškodit svá data? Protože to je přesně to, co poškodí vaše data!

Démon Docker byl jasně navržen tak, aby měl výhradní přístup k /var/lib/docker. Nic jiného by se nemělo „dotýkat, šťouchat ani šťourat“ žádné soubory Dockeru umístěné v této složce.

proč tomu tak je? Protože toto je výsledek jedné z nejtěžších lekcí získaných při vývoji dotCloud. Kontejnerový engine dotCloud běžel tak, že k /var/lib/dotcloud přistupovalo současně několik procesů. Chytré triky, jako je atomické nahrazování souborů (místo úprav na místě), opepření kódu pomocí poradních a povinných zámků a další experimenty se zabezpečenými systémy, jako je SQLite a BDB, ne vždy fungovaly. Když jsme předělávali náš kontejnerový engine, ze kterého se nakonec stal Docker, jedním z velkých návrhových rozhodnutí bylo sjednotit všechny kontejnerové operace pod jediného démona, aby se odstranily všechny nesmysly o souběžnosti.

Nechápejte mě špatně: je zcela možné vyrobit něco dobrého, spolehlivého a rychlého, co zahrnuje více procesů a moderní paralelní řízení. Ale myslíme si, že je jednodušší a snazší psát a udržovat kód pomocí Dockeru jako jediného hráče.

To znamená, že pokud sdílíte adresář /var/lib/docker mezi více instancemi Dockeru, budete mít problémy. To samozřejmě může fungovat, zvláště v raných fázích testování. "Poslouchej, mami, můžu spustit ubuntu jako docker!" Ale zkuste něco složitějšího, jako je vytažení stejného obrázku ze dvou různých instancí, a uvidíte, jak svět hoří.

To znamená, že pokud váš systém CI provádí sestavení a přestavby, pokaždé, když restartujete kontejner Docker-in-Docker, riskujete, že do jeho mezipaměti spadne atomovka. To není vůbec cool!

Řešení

Udělejme krok zpět. Opravdu potřebujete Docker-in-Docker nebo jen chcete mít možnost spouštět Docker a sestavovat a spouštět kontejnery a obrazy z vašeho systému CI, zatímco samotný systém CI je v kontejneru?

Vsadím se, že většina lidí chce druhou možnost, což znamená, že chtějí, aby systém CI jako Jenkins mohl provozovat kontejnery. Nejjednodušší způsob, jak toho dosáhnout, je jednoduše vložit soket Docker do vašeho kontejneru CI a přiřadit jej k parametru -v.

Jednoduše řečeno, když spustíte svůj kontejner CI (Jenkins nebo jiný), místo toho, abyste něco hackovali spolu s Docker-in-Docker, začněte to řádkem:

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

Tento kontejner bude mít nyní přístup k soketu Docker, a proto bude moci spouštět kontejnery. Až na to, že místo spouštění „dětských“ kontejnerů spustí „sourozenecké“ kontejnery.

Zkuste to pomocí oficiálního obrazu dockeru (který obsahuje binární soubor Docker):

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

Vypadá a funguje jako Docker-in-Docker, ale není to Docker-in-Docker: když tento kontejner vytvoří další kontejnery, budou vytvořeny v Dockeru nejvyšší úrovně. Nezaznamenáte vedlejší účinky vnoření a mezipaměť sestavení bude sdílena v rámci více volání.

Poznámka: Předchozí verze tohoto článku doporučovaly propojit binární soubor Docker z hostitele s kontejnerem. To se nyní stalo nespolehlivé, protože Docker engine již nepokrývá statické nebo téměř statické knihovny.

Pokud tedy chcete používat Docker od Jenkins CI, máte 2 možnosti:
instalace Docker CLI pomocí základního systému balení obrazu (tj. pokud je váš obraz založen na Debianu, použijte balíčky .deb) pomocí rozhraní Docker API.

Nějaké inzeráty 🙂

Děkujeme, že s námi zůstáváte. Líbí se vám naše články? Chcete vidět více zajímavého obsahu? Podpořte nás objednávkou nebo doporučením přátelům, cloud VPS pro vývojáře od 4.99 $, jedinečný analog serverů základní úrovně, který jsme pro vás vymysleli: Celá pravda o VPS (KVM) E5-2697 v3 (6 jader) 10GB DDR4 480GB SSD 1Gbps od 19 $ nebo jak sdílet server? (k dispozici s RAID1 a RAID10, až 24 jader a až 40 GB DDR4).

Dell R730xd 2krát levnější v datovém centru Equinix Tier IV v Amsterdamu? Pouze zde 2 x Intel TetraDeca-Core Xeon 2 x E5-2697v3 2.6 GHz 14C 64 GB DDR4 4 x 960 GB SSD 1 Gbps 100 TV od 199 USD V Nizozemsku! Dell R420 – 2x E5-2430 2.2 GHz 6C 128 GB DDR3 2 x 960 GB SSD 1 Gb/s 100 TB – od 99 $! Číst o Jak budovat infrastrukturu corp. třídy s využitím serverů Dell R730xd E5-2650 v4 v hodnotě 9000 XNUMX eur za cent?

Zdroj: www.habr.com

Přidat komentář