Մասնավոր փաթեթը, որը ձեր մեքենայում անխնդիր լուծվում է, կարող է build-ի ներսում ձախողվել 404-ով կամ ժամկետի ավարտով, և Dockerfile-ը հազվադեպ է պատճառը։ Build-ի քայլը աշխատում է այլ ցանցային անվանատարածքում՝ այլ DNS պատկերով և այլ հավատարմագրերի պահոցով, քան այն shell-ը, որտեղ փորձարկել եք։ Անցեք այս ստուգումները հերթականությամբ և կանգ առեք առաջին ձախողվածի վրա, որովհետև յուրաքանչյուր հաջորդ ստուգում ենթադրում է, որ նախորդն անցել է։ Յուրաքանչյուր քայլ անվանում է այն հրամանը, որը լուծում է հարցը։

Սկսեք builder-ի անունից, ոչ Dockerfile-ից

BuildKit-ը կարող է լինել տեղական, կոնտեյների մեջ կամ այլ մեքենայի վրա, և դրանցից յուրաքանչյուրն ունի իր լռելյայն ցանցը։ Գործարկեք docker buildx ls և կարդացեք աստղանիշով նշված հանգույցը նախքան որևէ բան փոխելը։ Մեկ docker-container դրայվեր կամ ամպային builder չի կիսում ձեր նոթբուքի մասնավոր ուղին միայն այն պատճառով, որ դուք հրամանը մուտքագրել եք այնտեղ։ Եթե ակտիվ builder-ը հեռավոր է, մնացած յուրաքանչյուր ստուգում պետք է կատարվի այդ հյուրընկալի վրա, ոչ ձեր աշխատանքային կայանում։

Builder-ը նաև կրում է իր resolver-ի կարգավորումը և proxy փոփոխականները։ Երկուսն էլ կարդացվում են build-ի պահին և չեն ժառանգվում այն տերմինալից, որը սկսել է build-ը։

Ապացուցեք ցանցային ուղին build-ի քայլի ներսից

Գրեք միանվագ փուլ, որը լուծում է կախվածության հյուրընկալին և կապ է բացում դեպի այն։ Սա միակ փորձարկումն է, որը պատասխանում է հարցին builder-ի, այլ ոչ ձեր shell-ի համար։

FROM alpine:3.20
RUN apk add --no-cache curl bind-tools  && getent hosts registry.example.internal  && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/

Կառուցեք այդ ֆայլը նույն builder-ով, ցանցային ռեժիմով և նույն secret-ամրացումներով, որոնք օգտագործում է ձեր իրական build-ը: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .։ Եթե getent ոչինչ չտպի, ապա խնդիրը անվանման լուծման մեջ է, և ոչ մի հավատարմագիր դա չի ուղղի։ Եթե անունը լուծվում է, բայց curl-ը հաղորդում է ժամկետի ավարտի մասին, արգելքը երթուղին է կամ ռեգիստրի առջևի ելքի քաղաքականությունը։

Ջնջեք զոնդը հենց որ պատասխանի։ Սա ախտորոշիչ փուլ է, և այն երբեք չպետք է պիտակվի կամ push արվի։

Ամրացրեք հավատարմագիրը՝ այն պատճենելու փոխարեն

Երբ ուղին աշխատի, նույնականացումը հաջորդ ձախողումն է հերթում։ BuildKit-ի secret-ամրացումը ֆայլը հասանելի է դարձնում մեկ RUN քայլի՝ առանց այն շերտում գրելու, դա է, ինչ պետք է կախվածության գործիքին, և ինչը image-ը չպետք է պահի։

RUN --mount=type=secret,id=npmrc,target=/root/.npmrc     npm ci --omit=dev

Գաղտնիքը պետք է մատակարարվի Dockerfile-ից դուրս: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .։ Ֆայլը մնում է հաճախորդի մոտ և երբեք չի մտնում image-ի պատմության մեջ։ Մեկ ARG կամ ENV նույն token-ով չեն կատարում այս աշխատանքը, որովհետև երկուսն էլ գրանցվում են image-ի կոնֆիգուրացիայում։

Ոչ root image-ին պետք է իր նպատակային ուղին, օրինակ /home/app/.npmrc կամ համարժեք ֆայլը pip-ի, Maven-ի կամ Cargo-ի համար։ Ամրացման նպատակը պետք է համապատասխանի հրամանը գործարկող օգտատիրոջը, այլապես գործիքը կհայտնի բացակայող կոնֆիգուրացիոն ֆայլի մասին, որը իրականում կա։

Ստուգեք, թե ինչ է թողնում կախվածության գործիքը image-ում

Ժամանակավոր ամրացումը հավատարմագիրը պահում է շերտից դուրս, բայց չի խանգարում գործիքին այլ բան գրել։ Փաթեթների կառավարիչները թողնում են lock ֆայլեր, cache թղթապանակներ և երբեմն լուծված ռեգիստրի URL-ը։

Կարդացեք պատրաստի ֆայլային համակարգը՝ Dockerfile-ին վստահելու փոխարեն։ docker history --no-trunc image:tag թվարկում է յուրաքանչյուր շերտի հրամանը, և docker run --rm image:tag sh -c "ls -a /root" ցույց է տալիս, թե ինչ է փրկվել աշխատող կոնտեյներում։ Նույնիսկ երբ ֆայլը միայն ամրացված էր, log տողում գրված token-ը npm ci ընթացքում նույնպես արտահոսք է մնում։

Կարդացեք նաև build-ի լոգը, որովհետև --progress=plain տպում է հրամանների ելքը բառացի։ Եթե token-ը հայտնվում է այնտեղ, պտտեք այն ամեն ինչից առաջ և փոխանցեք ֆայլի միջով, որը գործիքը կարդում է լուռ։

Համոզվեք, որ աշխատանքի պահի image-ին այլևս պետք չէ մասնավոր ուղին

Build-ը և աշխատող հավելվածը նույն կախվածության երկու տարբեր սպառողներ են, և մասնավոր ուղին պետք է միայն առաջինին։ Պատրաստ image-ը պետք է մեկնարկի, լուծի իր աշխատանքային կախվածությունները և սպասարկի երթևեկությունը առանց build-ի հավատարմագրի։

Փորձարկեք այնտեղ, որտեղ մասնավոր ռեգիստրը անհասանելի է, կամ պարզապես գործարկեք կոնտեյները --network none և հաստատեք, որ այն բեռնվում է առանց ամրացված գաղտնիքի։ Կոնտեյները, որը մեկնարկում է միայն build-ի գաղտնիքի առկայությամբ, դեռ կապված է build-ի միջավայրին։

Եթե կոնտեյներին իսկապես անհրաժեշտ է ռեգիստրը աշխատանքի պահին, դա առանձին հասանելիության որոշում է, և դրա տեղը նվագախմբի գաղտնիքների պահոցն է, ոչ build-ը։ Փաստագրեք երկու ուղիներն առանձին, որպեսզի ոչ ոք չփորձի վերանորոգել աշխատանքի պահի pull-ը build-ի դրոշով։ Երբ բոլոր հինգ ստուգումներն անցնեն, սկզբնական ախտանիշը յուրաքանչյուր շերտում ունի անվանված պատճառ՝ Docker-ի ցանցի մասին ենթադրության փոխարեն։

Առնչվող հոդվածներ