Docker-in-Docker-ը վիրտուալացված Docker daemon միջավայր է, որն աշխատում է հենց կոնտեյների ներսում՝ կոնտեյների պատկերներ ստեղծելու համար: Docker-in-Docker-ի ստեղծման հիմնական նպատակն էր օգնել Docker-ի զարգացմանը: Շատ մարդիկ օգտագործում են այն Jenkins CI-ն գործարկելու համար: Սա սկզբում նորմալ է թվում, բայց հետո խնդիրներ են առաջանում, որոնցից կարելի է խուսափել՝ տեղադրելով Docker-ը Jenkins CI կոնտեյներով: Այս հոդվածը պատմում է ձեզ, թե ինչպես դա անել: Եթե ձեզ հետաքրքրում է վերջնական լուծումն առանց մանրամասների, պարզապես կարդացեք հոդվածի վերջին բաժինը՝ «Խնդրի լուծում»:
Docker-in-Docker: «Լավ»
Ավելի քան երկու տարի առաջ ես դրեցի Docker-ը
- hackity hack;
- կառուցել;
- դադարեցնել վազող Docker daemon-ը;
- նոր Docker daemon-ի գործարկում;
- թեստավորում;
- կրկնել ցիկլը:
Եթե ցանկանում էիք պատրաստել գեղեցիկ, վերարտադրվող հավաքույթ (այսինքն՝ տարայի մեջ), ապա այն ավելի բարդ դարձավ.
- hackity hack;
- համոզվեք, որ աշխատում է Docker-ի աշխատանքային տարբերակը.
- կառուցել նոր Docker հին Docker-ով;
- դադարեցնել Docker daemon;
- սկսել նոր Docker daemon;
- փորձարկում;
- դադարեցնել նոր Docker daemon;
- կրկնել.
Docker-in-Docker-ի գալուստով գործընթացն ավելի պարզ է դարձել.
- hackity hack;
- հավաքում + մեկնարկը մեկ փուլով;
- կրկնել ցիկլը:
Այսպես շատ ավելի լավ չէ՞:
Docker-in-Docker: «Վատ»
Այնուամենայնիվ, հակառակ տարածված կարծիքի, Docker-in-Docker-ը 100% աստղեր, պոնիներ և միաեղջյուրներ չեն: Ես նկատի ունեմ այն, որ կան մի քանի խնդիրներ, որոնց մասին պետք է տեղյակ լինի մշակողը:
Դրանցից մեկը վերաբերում է LSM-ներին (Linux անվտանգության մոդուլներին), ինչպիսիք են AppArmor-ը և SELinux-ը. կոնտեյներ աշխատելիս «ներքին Docker»-ը կարող է փորձել կիրառել անվտանգության պրոֆիլներ, որոնք հակասում են կամ շփոթեցնում «արտաքին Docker»-ը: Սա ամենադժվար խնդիրն է լուծել, երբ փորձում ենք միավորել –արտոնյալ դրոշի սկզբնական իրականացումը: Իմ փոփոխություններն աշխատեցին, և բոլոր թեստերը կփոխանցվեին իմ Debian մեքենայի և Ubuntu փորձարկման VM-ների վրա, բայց դրանք կխափանվեին և կվառվեին Մայքլ Քրոսբիի մեքենայի վրա (նա ուներ Fedora, ինչպես հիշում եմ): Ես չեմ կարող հիշել խնդրի ճշգրիտ պատճառը, բայց դա կարող է լինել այն պատճառով, որ Մայքը իմաստուն տղա է, ով աշխատում է SELINUX=enforce-ով (ես օգտագործել եմ AppArmor-ը), և իմ փոփոխությունները հաշվի չեն առել SELinux պրոֆիլները:
Docker-in-Docker: «Չար»
Երկրորդ խնդիրը կապված է Docker պահեստավորման դրայվերների հետ: Երբ դուք գործարկում եք Docker-in-Docker, արտաքին Docker-ն աշխատում է սովորական ֆայլային համակարգի վերևում (EXT4, BTRFS կամ ինչ ունեք), իսկ ներքին Docker-ն աշխատում է պատճենահանման վրա գրելու համակարգի վրա (AUFS, BTRFS, Device Mapper): և այլն): , կախված նրանից, թե ինչ է կազմաձևված արտաքին Docker-ն օգտագործելու համար): Սա ստեղծում է բազմաթիվ համակցություններ, որոնք չեն աշխատի: Օրինակ, դուք չեք կարողանա գործարկել AUFS-ը AUFS-ի վրա:
Եթե դուք գործարկում եք BTRFS-ը BTRFS-ի վերևում, այն սկզբում պետք է աշխատի, բայց երբ կան ներդիր ենթածավալներ, մայր ենթածավալը ջնջելը չի հաջողվի: Device Mapper մոդուլը չունի անվանատարածք, այնպես որ, եթե Docker-ի մի քանի օրինակներ այն գործարկեն միևնույն մեքենայի վրա, նրանք բոլորը կկարողանան տեսնել (և ազդել) պատկերները միմյանց և կոնտեյների պահեստային սարքերի վրա: Սա վատ է:
Այս խնդիրներից շատերը լուծելու համար կան լուծումներ: Օրինակ, եթե ցանկանում եք օգտագործել AUFS-ը ներքին Docker-ում, պարզապես վերածեք /var/lib/docker թղթապանակը ծավալի, և դուք լավ կլինեք: Docker-ը մի քանի բազային անունների տարածքներ է ավելացրել Device Mapper-ի թիրախային անուններին, որպեսզի եթե Docker-ի մի քանի զանգեր միևնույն մեքենայի վրա են, դրանք միմյանց վրա չենթարկվի:
Այնուամենայնիվ, նման կարգավորումը ամենևին էլ պարզ չէ, ինչպես երևում է դրանցից
Docker-in-Docker. Այն վատանում է
Ինչ վերաբերում է կառուցման քեշին: Սա նույնպես կարող է բավականին դժվար լինել: Մարդիկ հաճախ ինձ հարցնում են. «եթե ես գործարկում եմ Docker-in-Docker-ը, ինչպե՞ս կարող եմ օգտագործել իմ հոսթի վրա տեղադրված պատկերները՝ ամեն ինչ ետ քաշելու իմ ներքին Docker-ում»:
Որոշ նախաձեռնող մարդիկ փորձել են կապել /var/lib/docker-ը հյուրընկալողից Docker-in-Docker կոնտեյների հետ: Երբեմն նրանք կիսում են /var/lib/docker-ը բազմաթիվ կոնտեյներների հետ:
Ցանկանու՞մ եք փչացնել ձեր տվյալները: Քանի որ սա հենց այն է, ինչը կվնասի ձեր տվյալները:
Docker daemon-ը հստակ նախագծված էր բացառիկ մուտք ունենալու համար /var/lib/docker: Ուրիշ ոչինչ չպետք է «դիպչի, խփի կամ առաջացնի» Docker ֆայլերը, որոնք գտնվում են այս թղթապանակում:
Ինչո՞ւ է սա այդպես։ Քանի որ սա dotCloud-ի մշակման ընթացքում քաղված ամենադժվար դասերից մեկի արդյունքն է: DotCloud բեռնարկղային շարժիչն աշխատում էր մի քանի պրոցեսներով, որոնք միաժամանակ մուտք էին գործում /var/lib/dotcloud: Խորամանկ հնարքները, ինչպիսիք են ատոմային ֆայլի փոխարինումը (տեղում խմբագրելու փոխարեն), խորհրդատվական և պարտադիր կողպեքներով ծածկագրելը և այլ փորձեր անվտանգ համակարգերով, ինչպիսիք են SQLite-ը և BDB-ն, միշտ չէ, որ աշխատում էին: Երբ մենք վերանախագծում էինք մեր կոնտեյներային շարժիչը, որն ի վերջո դարձավ Docker, դիզայնի մեծ որոշումներից մեկն այն էր, որ կոնտեյներների բոլոր գործառնությունները համախմբվեն մեկ դեյմոնի ներքո՝ վերացնելու համաժամանակյա բոլոր անհեթեթությունները:
Ինձ սխալ չհասկանաք. լիովին հնարավոր է լավ, հուսալի և արագ ինչ-որ բան պատրաստել, որը ներառում է բազմաթիվ գործընթացներ և ժամանակակից զուգահեռ վերահսկողություն: Բայց մենք կարծում ենք, որ ավելի պարզ և հեշտ է գրել և պահպանել կոդը՝ օգտագործելով Docker-ը որպես միակ խաղացող:
Սա նշանակում է, որ եթե դուք կիսում եք /var/lib/docker գրացուցակը Docker-ի մի քանի օրինակների միջև, դուք խնդիրներ կունենաք: Իհարկե, դա կարող է աշխատել, հատկապես թեստավորման վաղ փուլերում: «Լսիր, մայրիկ, ես կարող եմ Ubuntu-ն գործարկել որպես դոկեր»: Բայց փորձեք ինչ-որ ավելի բարդ բան, օրինակ՝ նույն պատկերը երկու տարբեր օրինակներից հանելը, և կտեսնեք, որ աշխարհը այրվում է:
Սա նշանակում է, որ եթե ձեր CI համակարգը կառուցում և վերակառուցում է, ամեն անգամ, երբ դուք վերագործարկում եք ձեր Docker-in-Docker կոնտեյները, դուք վտանգում եք միջուկ գցել դրա քեշը: Սա ամենևին էլ թույն չէ:
Լուծումը
Եկեք մի քայլ հետ գնանք։ Ձեզ իսկապես անհրաժեշտ է Docker-in-Docker-ը, թե՞ պարզապես ցանկանում եք, որ կարողանաք գործարկել Docker-ը և կառուցել և գործարկել կոնտեյներներ և պատկերներ ձեր CI համակարգից, մինչ այդ CI համակարգը ինքնին գտնվում է կոնտեյների մեջ:
Գրազ եմ գալիս, որ մարդկանց մեծամասնությունը ցանկանում է վերջին տարբերակը, այսինքն՝ նրանք ցանկանում են, որ Ջենկինսի նման CI համակարգը կարողանա բեռնարկղեր վարել: Եվ դա անելու ամենահեշտ ձևը պարզապես Docker վարդակից տեղադրելն է ձեր CI կոնտեյների մեջ և այն կապել -v դրոշի հետ:
Պարզ ասած, երբ գործարկում եք ձեր CI կոնտեյները (Ջենկինս կամ այլ), Docker-in-Docker-ի հետ մեկտեղ ինչ-որ բան կոտրելու փոխարեն, սկսեք այն տողով.
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
Այս կոնտեյները այժմ մուտք կունենա Docker վարդակից և, հետևաբար, կկարողանա գործարկել բեռնարկղերը: Միայն թե «մանկական» կոնտեյներներ գործարկելու փոխարեն այն կգործարկի «եղբայր կամ եղբայր» կոնտեյներներ։
Փորձեք սա՝ օգտագործելով պաշտոնական դոկերի պատկերը (որը պարունակում է Docker երկուական):
docker run -v /var/run/docker.sock:/var/run/docker.sock
-ti docker
Այն արտաքինից և աշխատում է Docker-in-Docker-ի նման, բայց դա Docker-in-Docker չէ. երբ այս կոնտեյները ստեղծի լրացուցիչ կոնտեյներներ, դրանք կստեղծվեն վերին մակարդակի Docker-ում: Դուք չեք զգա բնադրման կողմնակի ազդեցությունները, և հավաքման քեշը կհամօգտագործվի բազմաթիվ զանգերի ընթացքում:
Նշում. Այս հոդվածի նախորդ տարբերակները խորհուրդ էին տալիս միացնել Docker երկուականը հոսթից դեպի կոնտեյներ: Սա այժմ դարձել է անհուսալի, քանի որ Docker շարժիչն այլևս չի ընդգրկում ստատիկ կամ գրեթե ստատիկ գրադարանները:
Այսպիսով, եթե ցանկանում եք օգտագործել Docker-ը Jenkins CI-ից, ունեք 2 տարբերակ.
Docker CLI-ի տեղադրում պատկերների փաթեթավորման հիմնական համակարգի միջոցով (այսինքն, եթե ձեր պատկերը հիմնված է Debian-ի վրա, օգտագործեք .deb փաթեթներ), օգտագործելով Docker API-ն:
Մի քանի գովազդ 🙂
Շնորհակալություն մեզ հետ մնալու համար: Ձեզ դուր են գալիս մեր հոդվածները: Ցանկանու՞մ եք տեսնել ավելի հետաքրքիր բովանդակություն: Աջակցեք մեզ՝ պատվիրելով կամ խորհուրդ տալով ընկերներին,
Dell R730xd 2 անգամ ավելի էժան Ամստերդամի Equinix Tier IV տվյալների կենտրոնում: Միայն այստեղ
Source: www.habr.com