इसमें कई तरह की तकनीकें शामिल हैं, जिनमें एक भी समाधान नहीं है। आप संभवतः निम्नलिखित में से कई करना चाहेंगे:
सबसे पहले, पुन: उपयोग के लिए अपनी छवि परतों का अनुकूलन करें। 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 जीबी नहीं ले सकती हैं।
2.37
बनाम1.47 GB