Dobro razmislite prije nego što koristite Docker-in-Docker za CI ili testno okruženje

Dobro razmislite prije nego što koristite Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker je virtuelizirani Docker demon koji radi na samom kontejneru za izgradnju slika kontejnera. Glavna svrha kreiranja Docker-in-Docker-a bila je pomoć u razvoju samog Docker-a. Mnogi ljudi ga koriste za pokretanje Jenkins CI. Ovo se u početku čini normalnim, ali onda nastaju problemi koji se mogu izbjeći instaliranjem Dockera u Jenkins CI kontejner. Ovaj članak objašnjava kako to učiniti. Ako vas zanima konačno rješenje bez detalja, samo pročitajte posljednji odjeljak članka Rješavanje problema.

Dobro razmislite prije nego što koristite Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker: Dobro

Prije više od dvije godine stavio sam Docker zastava – privilegovan i napisao prva verzija dind. Cilj je bio pomoći glavnom timu da brže razvije Docker. Prije Docker-in-Docker-a, tipičan razvojni ciklus je bio:

  • hackity hack;
  • montaža (gradnja);
  • zaustaviti pokretanje Docker demona;
  • pokretanje novog Docker demona;
  • testiranje;
  • ciklus ponoviti.

Ako ste htjeli napraviti lijepu, ponovljivu montažu (odnosno u kontejneru), onda je postalo složenije:

  • hackity hack;
  • provjerite da li radi funkcionalna verzija Dockera;
  • izgraditi novi Docker sa starim Dockerom;
  • zaustaviti docker demon;
  • pokrenuti novi Docker demon;
  • test;
  • zaustaviti novi Docker demon;
  • ponovi.

Pojavom Docker-in-Docker-a, proces je pojednostavljen:

  • hackity hack;
  • montaža + pokretanje u jednom koraku;
  • ciklus ponoviti.

Nije li to mnogo bolje?

Dobro razmislite prije nego što koristite Docker-in-Docker za CI ili testno okruženje

Docker-in-Docker: "Loše"

Međutim, suprotno popularnom vjerovanju, Docker-in-Docker nije 100% zvijezda, poniji i jednorozi. Mislim, postoji nekoliko problema kojih programer mora biti svjestan.

Jedan se tiče LSM-ova (Linux sigurnosnih modula) kao što su AppArmor i SELinux: kada se pokreće kontejner, "interni Docker" može pokušati primijeniti sigurnosne profile koji će biti u sukobu ili zamagljivati ​​"spoljni Docker". Ovo je najteži problem za rješavanje kada se pokušava kombinirati originalna implementacija --privileged zastavice. Moje promjene su funkcionirale i svi testovi bi također prošli na mojoj Debian mašini i testirali Ubuntu VM, ali bi se srušili i spalili na mašini Michaela Crosbyja (imao je Fedoru koliko se sjećam). Ne mogu se sjetiti tačnog uzroka problema, ali možda je to zato što je Mike mudar čovjek koji radi sa SELINUX=enforce (koristio sam AppArmor) i moje promjene nisu poštovale SELinux profile.

Docker-in-Docker: "Zlo"

Drugi problem se odnosi na Docker drajvere za skladištenje. Kada pokrenete Docker-in-Docker, eksterni Docker radi na vrhu običnog sistema datoteka (EXT4, BTRFS, ili šta god imate), dok se interni Docker pokreće na sistemu kopiranja na upisivanje (AUFS, BTRFS , Device Mapper, itd.). , u zavisnosti od toga šta je konfigurisano da koristi eksterni Docker). U ovom slučaju postoji mnogo kombinacija koje neće raditi. Na primjer, nećete moći pokrenuti AUFS na vrhu AUFS-a.

Ako koristite BTRFS na vrhu BTRFS-a, ovo bi u početku trebalo funkcionirati, ali kada postoje ugniježđeni podvolumen, roditeljski podvolumen se ne može izbrisati. Modul Device Mapper je bez imenskog prostora, tako da ako ga više Docker instanci koristi na istoj mašini, svi će moći da vide (i utiču) na slike jedni drugih i uređaja za rezervnu kopiju kontejnera. Ovo je loše.

Postoje rješenja za rješavanje mnogih od ovih problema. Na primjer, ako želite da koristite AUFS u internom Docker-u, samo pretvorite /var/lib/docker folder u volumen i sve će biti u redu. Docker je dodao neke osnovne prostore imena imenima cilja uređaja Device Mapper tako da ako se više Docker poziva izvrši na istoj mašini, oni neće "nagaziti" jedan na drugog.

Međutim, ovo podešavanje nije nimalo jednostavno, kao što možete vidjeti iz ovih članci u dind spremištu na GitHubu.

Docker-in-Docker: Sve gore

Šta je sa keš memorijom za izgradnju? Ovo također može biti prilično nezgodno. Ljudi me često pitaju “ako koristim Docker-in-Docker, kako mogu koristiti slike koje se nalaze na mom hostu umjesto da ponovo povlačim sve u svom internom Docker-u”?

Neki preduzimljivi ljudi pokušali su povezati /var/lib/docker sa hosta na Docker-in-Docker kontejner. Ponekad dijele /var/lib/docker s više kontejnera.

Dobro razmislite prije nego što koristite Docker-in-Docker za CI ili testno okruženje
Želite oštetiti podatke? Jer upravo to će oštetiti vaše podatke!

Docker daemon je jasno dizajniran da ima ekskluzivni pristup /var/lib/docker. Ništa drugo ne bi trebalo "dodirnuti, bockati ili opipati" bilo koje Docker datoteke koje se nalaze u ovoj fascikli.

Zašto je tako? Zato što je to rezultat jedne od najtežih lekcija naučenih u razvoju dotCloud-a. DotCloud kontejnerski mehanizam je radio tako što je imao više procesa koji istovremeno pristupaju /var/lib/dotcloudu. Lukavi trikovi kao što su atomska zamjena fajlova (umjesto uređivanja na mjestu), začinjavanje koda savjetodavnim i obaveznim bravama i drugi eksperimenti sa sigurnim sistemima kao što su SQLite i BDB nisu uvijek radili. Kada smo redizajnirali naš motor kontejnera, koji je na kraju postao Docker, jedna od glavnih dizajnerskih odluka bila je da prikupimo sve operacije kontejnera pod jednim demonom kako bismo uklonili sve ove gluposti o konkurentnosti.

Nemojte me pogrešno shvatiti: potpuno je moguće napraviti nešto lijepo, pouzdano i brzo što uključuje više procesa i modernu paralelnu kontrolu. Ali mislimo da je lakše i lakše pisati i održavati kod uz Docker kao jedinog igrača.

To znači da ako dijelite /var/lib/docker direktorij na više Docker instanci, bit ćete u nevolji. Naravno, ovo može funkcionirati, posebno u ranim fazama testiranja. “Slušaj, mama, mogu pokrenuti ubuntu s docker-om!” Ali pokušajte nešto složenije, poput izvlačenja iste slike iz dvije različite instance, i vidjet ćete kako svijet gori.

To znači da ako vaš CI sistem gradi i rekonstruiše, onda svaki put kada ponovo pokrenete svoj Docker-in-Docker kontejner, rizikujete da bacite nuklearnu bombu u njegovu keš memoriju. Uopšte nije kul!

Rešavanje problema

Hajdemo korak unazad. Da li vam je zaista potreban Docker-in-Docker, ili samo želite da možete da pokrenete Docker, odnosno da pravite i pokrećete kontejnere i slike iz vašeg CI sistema, dok je sam taj CI sistem u kontejneru?

Kladim se da većina ljudi želi potonju opciju, tj. žele da CI sistem poput Jenkinsa može pokretati kontejnere. A najlakši način da to učinite je da jednostavno umetnete Docker utičnicu u svoj CI kontejner povezujući ga sa -v zastavicom.

Jednostavno rečeno, kada pokrenete svoj CI kontejner (Jenkins ili na neki drugi način), umjesto da hakujete zajedno sa Docker-in-Docker-om, započnite ga sa linijom:

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

Ovaj kontejner će sada imati pristup Docker socketu i stoga će moći pokretati kontejnere. Osim što će umjesto pokretanja "podređenih" kontejnera pokrenuti kontejnere "sestra".

Isprobajte ovo koristeći zvaničnu docker sliku (koja sadrži docker binarnu datoteku):

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

Izgleda i radi kao Docker-in-Docker, ali nije Docker-in-Docker: kada ovaj kontejner kreira dodatne kontejnere, oni će biti kreirani u Docker-u najvišeg nivoa. Nećete iskusiti nuspojave ugniježđenja, a keš sklopa će se dijeliti na više poziva.

Napomena: Prethodne verzije ovog članka savjetovale su povezivanje Docker binarne datoteke od hosta do kontejnera. Ovo je sada postalo nepouzdano jer se Docker engine više ne proširuje na statične ili skoro statične biblioteke.

Dakle, ako želite koristiti Docker iz Jenkins CI, imate 2 opcije:
instaliranje Docker CLI koristeći osnovni sustav pakiranja slika (tj. ako je vaša slika bazirana na Debianu, koristite .deb pakete), koristeći Docker API.

Neke reklame 🙂

Hvala vam što ste ostali s nama. Da li vam se sviđaju naši članci? Želite li vidjeti još zanimljivih sadržaja? Podržite nas naručivanjem ili preporukom prijateljima, cloud VPS za programere od 4.99 USD, jedinstveni analog servera početnog nivoa, koji smo mi izmislili za vas: Cijela istina o VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps od 19$ ili kako dijeliti server? (dostupno sa RAID1 i RAID10, do 24 jezgra i do 40GB DDR4).

Dell R730xd 2 puta jeftiniji u Equinix Tier IV data centru u Amsterdamu? Samo ovdje 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV od 199 USD u Holandiji! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - od 99 USD! Pročitajte o Kako izgraditi infrastrukturnu kompaniju. klase uz korišćenje Dell R730xd E5-2650 v4 servera u vrednosti od 9000 evra za peni?

izvor: www.habr.com

Dodajte komentar