उन्नत मल्टी-स्टेज बिल्ड टेम्पलेट

छवि


Dockerfile फ़ाइलों में मल्टी-स्टेज बिल्ड फ़ंक्शन आपको उच्च स्तर की कैशिंग और कम सुरक्षा के साथ छोटे कंटेनर चित्र बनाने की अनुमति देता है। इस लेख में, मैं आपको कुछ उन्नत टेम्पलेट दिखाऊंगा - बिल्ड और रन के बीच फ़ाइलों की प्रतिलिपि बनाने से अधिक कुछ। वे आपको फ़ंक्शन की अधिकतम दक्षता प्राप्त करने की अनुमति देते हैं। हालांकि, यदि आप मल्टी-स्टेज असेंबली के क्षेत्र में शुरुआती हैं, तो सबसे पहले, शायद, यह उपयोगकर्ता के मैनुअल को पढ़ने के लिए नहीं होगा।


संस्करण संगतता


मल्टीस्टेज बिल्ड सपोर्ट को संस्करण v17.05 में डॉकर में जोड़ा गया। सभी टेम्पलेट किसी भी बाद के संस्करण के साथ काम करते हैं, लेकिन कुछ अधिक कुशल हैं, बिल्डकिट सर्वर साइड का उपयोग करके लिंकर्स के लिए धन्यवाद। मान लें कि BuildKit प्रभावी रूप से अप्रयुक्त चरणों को छोड़ देता है और यदि संभव हो तो, उसी समय चरणों का निर्माण करता है (मैंने इन उदाहरणों को अलग से हाइलाइट किया है)। बिल्डकिट को वर्तमान में बिल्ड के लिए प्रायोगिक बैकएंड के रूप में मोबी में जोड़ा जा रहा है और यह डॉकर सीई v18.06 में उपलब्ध होना चाहिए। इसका उपयोग स्वायत्त रूप से या img परियोजना के हिस्से के रूप में भी किया जा सकता है।




स्टेज इनहेरिटेंस


मल्टी-स्टेज बिल्ड कई नए सिंटैक्स कॉन्सेप्ट्स को जोड़ता है। सबसे पहले, आप मंच से शुरू कर सकते हैं नाम के AS stagename में नाम AS stagename और इस चरण से फ़ाइलों की प्रतिलिपि बनाने के लिए COPY में --from=stagename उपयोग करें। वास्तव में, FROM कमांड और --from लेबल में बहुत अधिक समानताएं हैं, कुछ भी नहीं के लिए कि उनका समान नाम है। दोनों एक ही तर्क लेते हैं, इसे पहचानते हैं, और या तो इस बिंदु से एक नया चरण शुरू करते हैं, या फ़ाइल को कॉपी करने के लिए एक स्रोत के रूप में उपयोग करते हैं। यही है, वर्तमान चरण के लिए मूल छवि गुणवत्ता में पिछले चरण का उपयोग करने के लिए, आप न केवल --from=stagename , बल्कि स्टेज नाम FROM stagename भी ले सकते हैं। यह उपयोगी है यदि आप डॉकफ़िल में कई कमांड में समान भागों का उपयोग करते हैं: यह सामान्य कोड को कम करता है और इसके रखरखाव को सरल करता है, जिससे बच्चे के कदम अलग-अलग होते हैं। इस प्रकार, एक चरण का पुनर्निर्माण दूसरों के लिए विधानसभा कैश को प्रभावित नहीं करता है। तदनुसार, docker build समय प्रत्येक चरण को --target लेबल का उपयोग करके व्यक्तिगत रूप से इकट्ठा किया जा सकता है।


 FROM ubuntu AS base RUN apt-get update && apt-get install git FROM base AS src1 RUN git clone … FROM base as src2 RUN git clone … 

इस उदाहरण में, BuildKit में दूसरा और तीसरा चरण एक साथ बनाया गया है।


छवियों का प्रत्यक्ष उपयोग


FROM कमांड में असेंबली स्टेज नामों का उपयोग करने के बजाय जो पहले केवल छवि संदर्भों का समर्थन करता था, आप सीधे --from लेबल का उपयोग करके छवियों का उपयोग कर सकते हैं। यह इन छवियों से सीधे फ़ाइलों को कॉपी करने के लिए निकलता है। उदाहरण के लिए, निम्नलिखित कोड में linuxkit/ca-certificatesimage सीधे टीएलएस सीए जड़ों को वर्तमान चरण में कॉपी करता है।


 FROM alpine COPY --from=linuxkit/ca-certificates / / 

आम छवि उपनाम


बिल्ड चरण में आवश्यक रूप से कोई कमांड शामिल नहीं है; इसमें एकल FROM लाइन शामिल हो सकती है। यदि आप कई स्थानों पर छवि का उपयोग करते हैं, तो यह रीडिंग को सरल बना देगा और ऐसा कर देगा कि यदि आपको समग्र छवि को अपडेट करने की आवश्यकता है, तो आपको केवल एक पंक्ति को बदलने की आवश्यकता है।


 FROM alpine:3.6 AS alpine FROM alpine RUN … FROM alpine RUN … 

इस उदाहरण में, अल्पाइन छवि का उपयोग करने वाला प्रत्येक स्थान वास्तव में alpine:3.6 लिए प्रतिबद्ध है, alpine:latest नहीं alpine:latest । जब alpine:3.7 अपग्रेड करने का समय आता है, तो आपको एक पंक्ति को बदलने की आवश्यकता होगी, और इसमें कोई संदेह नहीं है: अब विधानसभा के सभी तत्व एक अद्यतन संस्करण का उपयोग करते हैं।


यह सब अधिक महत्वपूर्ण है जब निर्माण तर्क का उपयोग उपनाम में किया जाता है। निम्न उदाहरण पिछले एक के समान है, लेकिन उपयोगकर्ता को असेंबली के सभी उदाहरणों को फिर से परिभाषित करने की अनुमति देता है जिसमें अल्पाइन छवि --build-arg ALPINE_VERSION=value विकल्प सेट करके शामिल होती है। याद रखें: FROM कमांड में उपयोग किए गए किसी भी तर्क को पहले बिल्ड चरण से पहले निर्धारित किया जाना चाहिए।


 ARG ALPINE_VERSION=3.6 FROM alpine:${ALPINE_VERSION} AS alpine FROM alpine RUN … 

"से -" में निर्मित तर्क का उपयोग करना


COPY के --from लेबल में निर्दिष्ट मान में विधानसभा तर्क नहीं होने चाहिए। उदाहरण के लिए, निम्न उदाहरण अमान्य है।


 // THIS EXAMPLE IS INTENTIONALLY INVALID FROM alpine AS build-stage0 RUN … FROM alpine ARG src=stage0 COPY --from=build-${src} . . 

यह इस तथ्य के कारण है कि विधानसभा शुरू होने से पहले चरणों के बीच निर्भरताएं निर्धारित की जानी चाहिए। फिर सभी टीमों के निरंतर मूल्यांकन की आवश्यकता नहीं है। उदाहरण के लिए, alpine छवि में परिभाषित एक पर्यावरण चर --from मान के मूल्यांकन को प्रभावित कर सकता है। कारण हम FROM कमांड के तर्कों का मूल्यांकन कर सकते हैं क्योंकि ये तर्क किसी भी स्तर पर शुरू होने से पहले विश्व स्तर पर परिभाषित होते हैं। सौभाग्य से, जैसा कि हमें पहले पता चला, यह एक FROM कमांड का उपयोग करके उपनाम के चरण को परिभाषित करने और इसे संदर्भित करने के लिए पर्याप्त है।


 ARG src=stage0 FROM alpine AS build-stage0 RUN … FROM build-${src} AS copy-src FROM alpine COPY --from=copy-src . . 

अब, यदि आप असेंबली तर्क src ओवरराइड करते हैं, तो अंतिम COPY तत्व के लिए प्रारंभिक चरण स्विच हो जाएगा। कृपया ध्यान दें: यदि कुछ चरणों का उपयोग नहीं किया जाता है, तो केवल बिल्डकिट-आधारित लिंकर्स उन्हें प्रभावी रूप से छोड़ सकते हैं।


बिल्ड तर्क का उपयोग करते हुए स्थितियां


हमें Dockerfile के लिए IF/ELSE शैली स्थितियों के लिए समर्थन जोड़ने के लिए कहा गया था। हमें अभी तक पता नहीं है कि हम कुछ समान जोड़ेंगे, लेकिन भविष्य में हम बिल्डकिट में क्लाइंट समर्थन का उपयोग करने की कोशिश करेंगे। इस बीच, समान व्यवहार को प्राप्त करने के लिए, आप वर्तमान बहु-मंच अवधारणाओं (कुछ योजना के साथ) का उपयोग कर सकते हैं।


 // THIS EXAMPLE IS INTENTIONALLY INVALID FROM alpine RUN … ARG BUILD_VERSION=1 IF $BUILD_VERSION==1 RUN touch version1 ELSE IF $BUILD_VERSION==2 RUN touch version2 DONE RUN … 

पिछला उदाहरण IF/ELSE का उपयोग करते हुए रिकॉर्डिंग की स्थिति के लिए छद्म कोड दिखाता है। वर्तमान मल्टी-स्टेज बिल्ड के साथ समान व्यवहार प्राप्त करने के लिए, आपको विभिन्न शाखा शर्तों को अलग-अलग चरणों के रूप में परिभाषित करने और सही निर्भरता पथ का चयन करने के लिए एक तर्क का उपयोग करने की आवश्यकता हो सकती है।


 ARG BUILD_VERSION=1 FROM alpine AS base RUN … FROM base AS branch-version-1 RUN touch version1 FROM base AS branch-version-2 RUN touch version2 FROM branch-version-${BUILD_VERSION} AS after-condition FROM after-condition RUN … 

Dockerfile में अंतिम चरण after-condition चरण पर आधारित है, जो कि छवि उर्फ ​​( BUILD_VERSION बिल्ड BUILD_VERSION पर आधारित मान्यता प्राप्त) है। BUILD_VERSION के मूल्य के आधार पर, मध्य खंड के इस या उस चरण का चयन किया जाता है।


कृपया ध्यान दें: केवल बिल्डकिट-आधारित लिंकर अप्रयुक्त शाखाओं को छोड़ सकते हैं। लिंकर्स के पिछले संस्करणों में, सभी चरणों का निर्माण किया जाएगा, लेकिन अंतिम छवि बनाने से पहले, उनके परिणाम त्याग दिए जाएंगे।


न्यूनतम उत्पादन चरण के लिए विकास / परीक्षण सहायक


अंत में, चलो पिछले डॉक्यूमेंट के संयोजन के एक उदाहरण को देखते हैं कि कैसे एक डॉकफेराइल बनाने के लिए जो एक न्यूनतम उत्पादन छवि बनाता है और फिर एक विकास छवि का परीक्षण करने और बनाने के लिए अपनी सामग्री का उपयोग कर सकता है। आइए मूल Dockerfile उदाहरण से शुरू करें:


 FROM golang:alpine AS stage0 … FROM golang:alpine AS stage1 … FROM scratch COPY --from=stage0 /binary0 /bin COPY --from=stage1 /binary1 /bin 

जब एक न्यूनतम उत्पादन छवि बनाई जाती है, तो यह एक काफी सामान्य विकल्प है। लेकिन क्या होगा यदि आपको अंतिम चरण में इन बायनेरिज़ के साथ वैकल्पिक डेवलपर छवि प्राप्त करने या परीक्षण चलाने की आवश्यकता है? पहली बात यह है कि परीक्षण और विकास के चरणों में समान बायनेरिज़ की प्रतिलिपि बनाने के लिए बस ध्यान में आता है। समस्या यह है: इसमें कोई गारंटी नहीं है कि आप एक ही संयोजन में सभी उत्पादन बायनेरिज़ का परीक्षण करेंगे। अंतिम चरण में, कुछ बदल सकता है, लेकिन आप अन्य चरणों में इसी तरह के बदलाव करना भूल जाएंगे या बाइनरी फ़ाइलों की नकल करने के तरीके में गलती करेंगे। अंत में, हम एक अलग बाइनरी फ़ाइल का परीक्षण नहीं कर रहे हैं, लेकिन अंतिम छवि।


एक विकल्प उत्पादन चरण के बाद के विकास और परीक्षण चरण को निर्धारित करना और उत्पादन चरण की संपूर्ण सामग्री की प्रतिलिपि बनाना है। फिर डिफ़ॉल्ट चरण को फिर से अंतिम चरण बनाने के लिए उत्पादन चरण के लिए एक FROM कमांड का उपयोग करें।


 FROM golang:alpine AS stage0 … FROM scratch AS release COPY --from=stage0 /binary0 /bin COPY --from=stage1 /binary1 /bin FROM golang:alpine AS dev-env COPY --from=release / / ENTRYPOINT ["ash"] FROM golang:alpine AS test COPY --from=release / / RUN go test … FROM release 

डिफ़ॉल्ट रूप से, यह Dockerfile एक न्यूनतम डिफ़ॉल्ट छवि बनाना जारी रखेगा, जबकि, उदाहरण के लिए, विकल्प के साथ एक असेंबली --target=dev-env अंतिम संस्करण के सभी बायनेरिज़ वाले शेल के साथ एक छवि बनाएगा।




आशा है कि यह मददगार था और सुझाव दिया गया कि कैसे अधिक कुशल मल्टी-स्टेज डॉकफाइल्स बनाया जाए। यदि आप DockerCon2018 में भाग लेते हैं और मल्टी-स्टेज बिल्ड, Dockerfiles, BuildKit या किसी भी संबंधित विषय के बारे में अधिक जानना चाहते हैं, तो हॉलवे ट्रैक लिंकर के लिए साइन अप करें या योगदान और सहयोग या ब्लैक बेल्ट पटरियों के लिए डॉकर प्लेटफॉर्म आंतरिक बैठकों का पालन करें।

Source: https://habr.com/ru/post/hi433790/


All Articles