CI yoki sinov muhiti uchun Docker-in-Docker-dan foydalanishdan oldin yaxshilab o'ylab ko'ring

CI yoki sinov muhiti uchun Docker-in-Docker-dan foydalanishdan oldin yaxshilab o'ylab ko'ring

Docker-in-Docker - bu konteyner tasvirlarini yaratish uchun konteyner ichida ishlaydigan virtuallashtirilgan Docker demon muhiti. Docker-in-Docker-ni yaratishning asosiy maqsadi Docker-ning o'zini rivojlantirishga yordam berish edi. Ko'p odamlar Jenkins CI-ni ishga tushirish uchun foydalanadilar. Avvaliga bu normaldek tuyuladi, ammo keyin Docker-ni Jenkins CI konteyneriga o'rnatish orqali oldini olish mumkin bo'lgan muammolar paydo bo'ladi. Ushbu maqolada buni qanday qilish kerakligi aytiladi. Agar siz batafsil ma'lumotsiz yakuniy yechimga qiziqsangiz, maqolaning oxirgi qismini "Muammoni hal qilish" ni o'qing.

CI yoki sinov muhiti uchun Docker-in-Docker-dan foydalanishdan oldin yaxshilab o'ylab ko'ring

Docker-in-Docker: "Yaxshi"

Ikki yildan ko'proq vaqt oldin men Docker-ga kiritdim bayroq - imtiyozli va yozgan dindning birinchi versiyasi. Maqsad asosiy jamoaga Dockerni tezroq rivojlantirishga yordam berish edi. Docker-in-Docker-dan oldin odatdagi rivojlanish tsikli quyidagicha ko'rinardi:

  • hackity hack;
  • qurmoq;
  • ishlaydigan Docker demonini to'xtatish;
  • yangi Docker demonini ishga tushirish;
  • sinov;
  • tsiklni takrorlang.

Agar siz chiroyli, takrorlanadigan yig'ilishni (ya'ni idishda) qilishni istasangiz, u yanada murakkablashdi:

  • hackity hack;
  • Dockerning ishlaydigan versiyasi ishlayotganligiga ishonch hosil qiling;
  • eski Docker bilan yangi Docker yaratish;
  • Docker demonini to'xtatish;
  • yangi Docker demonini ishga tushiring;
  • sinov;
  • yangi Docker demonini to'xtatish;
  • takrorlang.

Docker-in-Docker-ning paydo bo'lishi bilan jarayon soddalashdi:

  • hackity hack;
  • yig'ish + bir bosqichda ishga tushirish;
  • tsiklni takrorlang.

Shu tarzda yaxshiroq emasmi?

CI yoki sinov muhiti uchun Docker-in-Docker-dan foydalanishdan oldin yaxshilab o'ylab ko'ring

Docker-in-Docker: "Yomon"

Biroq, mashhur e'tiqoddan farqli o'laroq, Docker-in-Docker 100% yulduzlar, ponilar va yagona shoxlar emas. Men shuni nazarda tutyapmanki, ishlab chiquvchi bilishi kerak bo'lgan bir nechta muammolar mavjud.

Ulardan biri AppArmor va SELinux kabi LSM (Linux xavfsizlik modullari) bilan bog'liq: konteynerni ishga tushirganda, "ichki Docker" "tashqi Docker" ga zid keladigan yoki chalkashtirib yuboradigan xavfsizlik profillarini qo'llashga urinishi mumkin. Imtiyozli bayroqning asl tatbiqini birlashtirishga urinayotganda, bu eng qiyin muammodir. Mening o'zgarishlarim ishladi va barcha testlar mening Debian mashinam va Ubuntu sinov VM-larida o'tadi, lekin ular Maykl Krosbining mashinasida ishdan chiqadi va yonib ketadi (esimda, u Fedora edi). Muammoning aniq sababini eslay olmayman, lekin Mayk SELINUX=enforce (men AppArmor’dan foydalanganman) bilan ishlaydigan dono yigit bo‘lgani va mening o‘zgarishlarim SELinux profillarini hisobga olmagani bo‘lishi mumkin.

Docker-in-Docker: "Yovuzlik"

Ikkinchi muammo Docker xotira drayverlari bilan bog'liq. Docker-in-Docker-ni ishga tushirganingizda, tashqi Docker oddiy fayl tizimi (EXT4, BTRFS yoki sizda mavjud bo'lgan narsa) ustida ishlaydi va ichki Docker yozma nusxa ko'chirish tizimi (AUFS, BTRFS, Device Mapper) ustida ishlaydi. va boshqalar). , tashqi Docker-dan foydalanish uchun nima sozlanganiga qarab). Bu ishlamaydigan ko'plab kombinatsiyalarni yaratadi. Masalan, siz AUFS-ni AUFS-ning tepasida ishlata olmaysiz.

Agar siz BTRFS-ni BTRFS-ning tepasida ishlatsangiz, u dastlab ishlashi kerak, lekin ichki ichki jildlar mavjud bo'lganda, asosiy pastki jildni o'chirish muvaffaqiyatsiz bo'ladi. Device Mapper moduli nom maydoniga ega emas, shuning uchun agar bir nechta Docker nusxalari uni bitta mashinada ishlayotgan bo'lsa, ularning barchasi bir-biridagi va konteyner zaxira qurilmalaridagi tasvirlarni ko'ra oladi (va ta'sir qiladi). Bu yomon.

Ushbu muammolarning ko'pini hal qilish uchun vaqtinchalik echimlar mavjud. Misol uchun, agar siz ichki Docker-da AUFS-dan foydalanmoqchi bo'lsangiz, shunchaki /var/lib/docker jildini jildga aylantiring va siz yaxshi bo'lasiz. Docker bir nechta Docker qo'ng'iroqlari bir xil mashinada ishlayotgan bo'lsa, ular bir-biriga qadam qo'ymasliklari uchun Device Mapper maqsad nomlariga ba'zi asosiy nom maydonlarini qo'shdi.

Biroq, bulardan ko'rinib turganidek, bunday sozlash umuman oddiy emas maqolalar GitHub-dagi dind omborida.

Docker-in-Docker: Bu yomonlashadi

Qurilish keshi haqida nima deyish mumkin? Bu ham juda qiyin bo'lishi mumkin. Odamlar mendan tez-tez so'rashadi: "Agar men Docker-in-Docker-da ishlayotgan bo'lsam, hamma narsani ichki Docker-ga qaytarish o'rniga xostda joylashtirilgan tasvirlardan qanday foydalanishim mumkin?"

Ba'zi tashabbuskor odamlar /var/lib/docker-ni xostdan Docker-in-Docker konteyneriga ulashga harakat qilishdi. Ba'zan ular /var/lib/docker-ni bir nechta konteynerlar bilan bo'lishadi.

CI yoki sinov muhiti uchun Docker-in-Docker-dan foydalanishdan oldin yaxshilab o'ylab ko'ring
Ma'lumotlaringizni buzmoqchimisiz? Chunki aynan shu narsa ma'lumotlaringizga zarar yetkazadi!

Docker demoni /var/lib/docker-ga eksklyuziv kirish huquqiga ega bo'lishi uchun aniq ishlab chiqilgan. Ushbu jildda joylashgan Docker fayllariga boshqa hech narsa “tegishi, tepishi yoki ishlab chiqarishi” kerak emas.

Nega bunday? Chunki bu dotCloudni ishlab chiqishda olingan eng qiyin saboqlardan biri natijasidir. DotCloud konteyner dvigateli bir vaqtning o'zida /var/lib/dotcloud-ga bir nechta jarayonlarga kirish orqali ishladi. Atom faylini almashtirish (joyida tahrir qilish o'rniga), maslahat va majburiy qulflar bilan qalampirlash kodlari va SQLite va BDB kabi xavfsiz tizimlar bilan boshqa tajribalar kabi hiyla-nayranglar har doim ham ish bermadi. Oxir-oqibat Dockerga aylangan konteyner dvigatelimizni qayta loyihalashtirganimizda, eng katta dizayn qarorlaridan biri barcha konteyner operatsiyalarini bitta demon ostida birlashtirish edi.

Meni noto'g'ri tushunmang: bir nechta jarayonlarni va zamonaviy parallel boshqaruvni o'z ichiga olgan yaxshi, ishonchli va tezkor narsalarni qilish mutlaqo mumkin. Lekin bizning fikrimizcha, yagona o'yinchi sifatida Docker-dan foydalanib kod yozish va unga xizmat ko'rsatish osonroq va osonroq.

Bu shuni anglatadiki, agar siz /var/lib/docker katalogini bir nechta Docker misollari orasida baham ko'rsangiz, sizda muammolar paydo bo'ladi. Albatta, bu, ayniqsa sinovning dastlabki bosqichlarida ishlashi mumkin. "Eshiting, onam, men ubuntuni doker sifatida boshqara olaman!" Ammo murakkabroq narsani sinab ko'ring, masalan, bir xil tasvirni ikki xil misoldan tortib oling, shunda dunyo yonayotganini ko'rasiz.

Bu shuni anglatadiki, agar sizning CI tizimingiz qurish va qayta qurishni amalga oshirsa, har safar Docker-in-Docker konteyneringizni qayta ishga tushirganingizda, uning keshiga yadro qo'yish xavfi bor. Bu umuman zo'r emas!

Muammolarni bartaraf etish

Keling, bir qadam orqaga qaytaylik. Sizga haqiqatan ham Docker-in-Docker kerakmi yoki siz shunchaki Docker-ni ishga tushirishni va CI tizimining o'zi konteynerda bo'lganda CI tizimingizdan konteynerlar va tasvirlarni qurish va ishga tushirishni xohlaysizmi?

Ishonchim komilki, ko'pchilik oxirgi variantni xohlaydi, ya'ni ular Jenkins kabi CI tizimi konteynerlarni ishga tushirishni xohlashadi. Va buni amalga oshirishning eng oson yo'li oddiygina Docker soketini CI konteyneringizga kiritish va uni -v bayrog'i bilan bog'lashdir.

Oddiy qilib aytganda, CI konteyneringizni (Jenkins yoki boshqa) ishga tushirganingizda, Docker-in-Docker bilan biror narsani buzish o'rniga, uni quyidagi qatordan boshlang:

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

Ushbu konteyner endi Docker soketiga kirish huquqiga ega bo'ladi va shuning uchun konteynerlarni ishga tushirishi mumkin. Bundan tashqari, "bolalar" konteynerlarini ishga tushirish o'rniga, "birodarlar" konteynerlarini ishga tushiradi.

Buni rasmiy docker tasviridan foydalanib ko'ring (u Docker binarini o'z ichiga oladi):

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

U Docker-in-Docker-ga o'xshaydi va ishlaydi, lekin u Docker-in-Docker emas: bu konteyner qo'shimcha konteynerlarni yaratganda, ular yuqori darajadagi Docker-da yaratiladi. Siz joylashtirishning nojo'ya ta'sirini sezmaysiz va yig'ish keshi bir nechta qo'ng'iroqlar bo'ylab baham ko'riladi.

Eslatma: Ushbu maqolaning oldingi versiyalarida Docker ikkilik faylini xostdan konteynerga ulash tavsiya etilgan. Bu endi ishonchsiz bo'lib qoldi, chunki Docker dvigateli endi statik yoki yaqin statik kutubxonalarni qamrab olmaydi.

Shunday qilib, agar siz Jenkins CI-dan Docker-dan foydalanmoqchi bo'lsangiz, sizda ikkita variant mavjud:
Docker CLI-ni asosiy tasvirlarni qadoqlash tizimidan foydalangan holda o'rnatish (ya'ni, agar sizning rasmingiz Debian-ga asoslangan bo'lsa, .deb paketlaridan foydalaning), Docker API yordamida.

Ba'zi reklamalar 🙂

Biz bilan qolganingiz uchun tashakkur. Bizning maqolalarimiz sizga yoqdimi? Ko'proq qiziqarli tarkibni ko'rishni xohlaysizmi? Buyurtma berish yoki do'stlaringizga tavsiya qilish orqali bizni qo'llab-quvvatlang, 4.99 dollardan boshlab ishlab chiquvchilar uchun bulutli VPS, Siz uchun biz tomonidan ixtiro qilingan boshlang'ich darajadagi serverlarning noyob analogi: VPS (KVM) E5-2697 v3 (6 yadroli) 10GB DDR4 480GB SSD 1Gbps 19 dollardan yoki serverni qanday almashish haqida butun haqiqat? (RAID1 va RAID10, 24 tagacha yadro va 40 Gb gacha DDR4 bilan mavjud).

Amsterdamdagi Equinix Tier IV ma'lumotlar markazida Dell R730xd 2 baravar arzonmi? Faqat shu yerda 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 televizor 199 dollardan Gollandiyada! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 dollardan! Haqida o'qing Infratuzilma korporatsiyasini qanday qurish kerak. bir tiyinga 730 evroga teng Dell R5xd E2650-4 v9000 serverlaridan foydalanish bilan sinf?

Manba: www.habr.com

a Izoh qo'shish