हर बार काम करने वाली छोटी छवि कैसे बनाएं?


19

उद्देश्य: हर बार सबसे छोटा काम करने वाले चित्र बनाना

वर्तमान

REPOSITORY          TAG       IMAGE ID            CREATED             SIZE
a-docker-image      latest    x                   42 minutes ago       1.92 GB

प्रयास

डॉकरफाइल के अंत में एक सफाई कदम जोड़ना:

#clean
RUN apt-get purge -y wget
RUN rm -r a-build-dir
RUN apt-get purge -y a-package

छवि का आकार थोड़ा कम:

REPOSITORY          TAG       IMAGE ID            CREATED             SIZE
a-docker-image      latest    y                   2 minutes ago       1.86 GB

विचार-विमर्श

मैंने विभिन्न डॉकटर चित्र बनाए हैं। हर बार मैं बनाई गई छवि के आकार को कम करने की कोशिश करता हूं, लेकिन मुझे हमेशा लगता है कि यह बहुत बड़ी है। मैं एक ऐसी स्क्रिप्ट की तलाश कर रहा हूं जो पहले से ही जीथब पर किसी द्वारा बनाई गई हो जो छवि से सभी शानदार पैकेजों को हटा देती है इसलिए बनाई गई छवि का आकार जितना संभव हो उतना छोटा होगा।

जैसा कि मैंने कहा कि मैं हमेशा छवि के आकार को कम करने की कोशिश करता हूं, लेकिन मैं इसे लगातार लागू करना चाहता हूं ताकि अब से मैं जो भी छवि बनाऊंगा वह उतना ही छोटा होगा।

सवाल

हर बार काम करने वाली छोटी छवि कैसे बनाएं?

जवाबों:


1

इसमें कई तरह की तकनीकें शामिल हैं, जिनमें एक भी समाधान नहीं है। आप संभवतः निम्नलिखित में से कई करना चाहेंगे:


सबसे पहले, पुन: उपयोग के लिए अपनी छवि परतों का अनुकूलन करें। Dockerfile में बाद में बार-बार बदलते कदमों को बढ़ाएं ताकि पिछली बिल्ड्स से जल्दी लेयर्स को कैश किया जा सके। एक पुन: उपयोग की गई परत अधिक डिस्क स्थान के रूप में दिखाई देगी docker image ls, लेकिन यदि आप अंतर्निहित फाइल सिस्टम की जांच करते हैं, तो प्रत्येक परत की केवल एक प्रतिलिपि कभी भी डिस्क पर संग्रहीत होती है। इसका मतलब है कि प्रत्येक में 2 जीबी की 3 छवियां हैं, लेकिन जो निर्माण की अंतिम कुछ परतों में केवल 50 एमबी अलग हैं, केवल 2.1 जीबी डिस्क स्थान लेगी, भले ही सूची में यह प्रकट होता है कि वे 6 जीबी का उपयोग कर रहे हैं क्योंकि आप हैं पुन: उपयोग की गई परतों में से प्रत्येक की दोहरी गणना।

लेयर का पुन: उपयोग इसीलिए होता है कि आप कोड में कॉपी करने से पहले उन बदलावों को देखते हैं, जो निर्माण निर्भरता को बदलते हैं। कोई भी अजगर उदाहरण देखें जिसमें एक पैटर्न है:

FROM python
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# note how the code is copied only after the pip install
# since code changes but requirements.txt doesn't
COPY . .
CMD ["gunicorn", "app:app"]

न्यूनतम आधार छवि चुनें। यह वह जगह है तुम क्यों देख लोग से जाना ubuntuकरने के लिए debian:slim(स्लिम वेरिएंट, छोटे होते हैं कम उपकरणों के साथ शिपिंग), या यहाँ तक alpine। यह आपके शुरुआती बिंदु के आकार को कम करता है, और यदि आप आधार छवि के नए संस्करणों को लगातार खींच रहे हैं तो यह बहुत मददगार है। हालांकि, यदि आपकी आधार छवि शायद ही कभी बदलती है, तो परत का पुन: उपयोग न्यूनतम आधार छवि के लाभ को हटा देता है।

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


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

RUN apt-get update \
 && apt-get install -y \
      a-package \
      wget \
 && ... \
 && apt-get purge -y wget \
 && rm -r a-build-dir \
 && apt-get purge -y a-package

ध्यान दें कि कमांड चेनिंग का अति प्रयोग आपके बिल्ड को धीमा कर सकता है क्योंकि आपको उसी टूलसेट को फिर से इंस्टॉल करने की आवश्यकता होती है जब भी कोई पूर्वापेक्षा परिवर्तन (जैसे कोड को wget के साथ खींचा जा रहा है)। बेहतर विकल्प के लिए नीचे मल्टी-स्टेज देखें।


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

# first create and leave containers from any RUN step using options on build
docker image build --rm=false --no-cache -t image_name . 
# review which layers use an unexpectedly large amount of space
docker image history image_name
# list all containers, particularly the exited ones from above
docker container ps -a 
# examine any of those containers
docker container diff ${container_id} 
# ... repeat the diff for other build steps
# then cleanup exited containers
docker container prune

उन मध्यस्थ पात्र में से प्रत्येक के साथ, अंतर दिखा देंगे क्या फ़ाइलें, जोड़ा बदल गया है, या उस चरण में नष्ट हो जाती हैं (इनके लिए साथ दिखाई देते हैं A, Cया Dप्रत्येक फ़ाइल नाम से पहले)। क्या अंतर दिखा रहा है कंटेनर विशिष्ट रीड / राइट फाइलसिस्टम है, जो किसी भी फाइल को कॉपी-ऑन-राइट का उपयोग करके छवि स्थिति से कंटेनर द्वारा बदल दिया जाता है।


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

FROM debian:9 as build
# still chain update with install to prevent stale cache issues
RUN apt-get update \
 && apt-get install -y \
      a-package \
      wget \
RUN ... # perform any download/compile steps

FROM debian:9-slim as release
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD [ "/usr/local/bin/app" ]

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


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


25

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

इसलिए यदि आप इसे बदलते हैं:

RUN apt-get update -y
RUN apt-get install -y wget a-package
# ...
RUN apt-get purge -y wget
RUN rm -r a-build-dir
RUN apt-get purge -y a-package

इसके लिए:

RUN apt-get update -y \
    && apt-get install -y wget a-package \
    && mkdir a-build-dir \
    && wget http://some-site/very-big-source-code.tar.gz \
    && tar xzvf very-big-source-code.tar.gz \
    && do-some-compilation \
    && apt-get purge -y wget \
    && cd .. \
    && rm -rf a-build-dir \
    && apt-get purge -y a-package

आपको बहुत छोटी छवि मिलेगी।


एक अन्य विकल्प, छवि बनाने के बाद इसे स्क्वाश करना है। प्रश्न: नया docker --squashकाम कैसे करता है ?


फिर भी एक और विकल्प, एक पतली आधार छवि चुनना है। उदाहरण के लिए, छवियाँ जो डेबियन के बजाय अल्पाइन लिनक्स को अपने आधार के रूप में उपयोग करती हैं, 180-250mb के बजाय सिर्फ 10-15mb लेती हैं। और यह आपके अपने आवेदन और डेटा को जोड़ने से पहले है। डॉकर हब पर कई आधिकारिक आधार चित्रों में एक अल्पाइन संस्करण है।


3
2.37बनाम1.47 GB
०३०

4

शायद एक जवाब नहीं, लेकिन विकल्प देने लायक।

शेफ के निवास स्थान को ध्यान में रखते हुए बनाया गया है, जो आप नहीं चाहते हैं कि बाहर के डिस्ट्रो / बेस इमेज लोड के बिना सभी आवश्यक निर्भरताओं के साथ एक पैकेज बना रहे हैं।

यहां जो मायने रखता है, उस पर अर्क, एक साधारण नोडज एप्लिकेशन के साथ इस ब्लॉग पोस्ट से कंटेनर का आकार :

michael@ricardo-2:plans_pkg_part_2$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
mfdii/node-example   latest              36c6568c606b        40 minutes ago      655.9 MB
node                 latest              04c0ca2a8dad        16 hours ago        654.6 MB
mfdii/mytutorialapp  latest              534afd80d74d        2 minutes ago       182.1 MB

mdfii/node-exampleएक क्लासिक dockerfile से डॉक mfdii/mytutorialappछवि है, जबकि डॉकटर छवि वास के साथ निर्मित है।

यदि आकार आपकी मुख्य चिंता है और आप पर्यावास योजनाओं के सीखने की अवस्था में हैं, तो यह आपके लिए एक समाधान हो सकता है।


0

एक भी गोता लगा सकता था

docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    wagoodman/dive:latest <dive arguments...>

आकार को कम करने के लिए डॉक छवि से कचरे को क्या हटाया जा सकता है, इसके बारे में एक रिपोर्ट प्राप्त करना।


0

यदि आप पुन: प्रयोज्य विकास परतें बनाना चाहते हैं, लेकिन वितरण के लिए अपने डिस्क उपयोग को कम कर सकते हैं, तो आप इस तरह एक मर्ज किए गए "वितरण परत" का उत्पादन कर सकते हैं:

  1. सुनिश्चित करें कि आपके पास एक कंटेनर है जो आपकी छवि का उपयोग करता है (यदि आपके पास एक नहीं है, तो शायद कुछ का उपयोग करें docker run IMAGE echo, जैसे कि इको कमांड उपलब्ध है)
  2. कंटेनर आईडी ढूंढें (शायद उपयोग करके docker container ls -l)
  3. पाइप docker exportके लिए docker importमर्ज किए गए परत बनाने के लिए (जैसे कुछ docker export 20f192c6530a | docker import - project:merged)

यह आपके विकास की परतों को बनाए रखेगा लेकिन आपको एक छोटी, मर्ज की गई छवि देगा जिसे आप वितरित कर सकते हैं।


0

मल्टी स्टेज बनाता है। उस छवि का उपयोग करें जिसमें आपके एप्लिकेशन बनाने के लिए आपके सभी बिल्ड घटक हैं, और एक हल्का रनटाइम छवि है। रनटाइम इमेज के लिए अपनी बिल्ड आर्टवर्क को कॉपी करें। कुछ भी हटाने की आवश्यकता नहीं है।

https://docs.docker.com/develop/develop-images/multistage-build/


0

सरल .. docker ps वर्तमान में चल रही छवियों की जाँच करें .. सरल फ़ाइल उदाहरण नीचे ..

Ubuntu16 से

MAINTAINER श्रीनि (ईमेल / डोमेन)

RUN एप-गेट अपडेट

RUN apt-get install -y nginx

ENTRYPOINT [”/ usr / sbin / nginx”, “- g”, “daemon off;”]

एक्सपो 80 (पोर्ट)

सरल docker फ़ाइल ...

नीचे दिए गए आदेश का उपयोग करें

docker रन -d -p 80:80 --name वेब सर्वर ubuntu16 (छवि नाम) उसके बाद लोकलहोस्ट या आईपी पते की जाँच करें: 80 (ब्राउज़र खोलें और जांचें)


1
कृपया उन्हें ठीक अपने जवाब के स्वरूपण ...
Pierre.Vriens
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.