जब संभव हो, मैं हमेशा एक साथ कमांड का विलय करता हूं जो कमांड के साथ फाइल बनाते हैं जो उन्हीं फाइलों को एक RUN
लाइन में हटाते हैं । ऐसा इसलिए है क्योंकि प्रत्येक RUN
पंक्ति छवि में एक परत जोड़ती है, आउटपुट काफी शाब्दिक रूप से फाइल सिस्टम में परिवर्तन होता है जिसे आप docker diff
अस्थायी कंटेनर के साथ देख सकते हैं जो इसे बनाता है। यदि आप किसी भिन्न परत में बनाई गई फ़ाइल को हटाते हैं, तो सभी यूनियन फ़ाइल सिस्टम एक नई परत में फाइल सिस्टम परिवर्तन को पंजीकृत करता है, फ़ाइल अभी भी पिछली परत में मौजूद है और इसे नेटवर्क पर भेज दिया जाता है और डिस्क पर संग्रहीत किया जाता है। इसलिए यदि आप स्रोत कोड डाउनलोड करते हैं, तो इसे निकालें, इसे एक बाइनरी में संकलित करें, और फिर अंत में tgz और स्रोत फ़ाइलों को हटा दें, आप वास्तव में छवि आकार को कम करने के लिए यह सब एक ही परत में करना चाहते हैं।
अगला, मैं व्यक्तिगत रूप से अन्य छवियों और पुन: उपयोग कैशिंग उपयोग में उनकी क्षमता के आधार पर परतों को विभाजित करता हूं। यदि मेरे पास 4 छवियां हैं, तो सभी एक ही आधार छवि (जैसे डेबियन) के साथ, मैं उन सभी छवियों में से अधिकांश के लिए आम उपयोगिताओं का एक संग्रह खींच सकता हूं ताकि पहले रन कमांड में अन्य छवियों को कैशिंग से लाभ हो।
छवि कैश पुन: उपयोग को देखते हुए डॉकरीफाइल में ऑर्डर महत्वपूर्ण है। मैं किसी भी घटक को देखता हूं जो शायद ही कभी अपडेट करेगा, संभवतः केवल जब आधार छवि अपडेट होती है और उन को डॉर्कफाइल में डाल दिया जाता है। Dockerfile के अंत की ओर, मैं किसी भी कमांड को शामिल करता हूं जो त्वरित चलेगा और बार-बार बदल सकता है, उदाहरण के लिए एक होस्ट विशिष्ट यूआईडी के साथ एक उपयोगकर्ता जोड़ना या फ़ोल्डर बनाना और अनुमतियां बदलना। यदि कंटेनर में व्याख्यायित कोड (उदाहरण के लिए जावास्क्रिप्ट) शामिल है जिसे सक्रिय रूप से विकसित किया जा रहा है, तो यह यथासंभव देर से जोड़ा जाता है ताकि एक पुनर्निर्माण केवल उस एकल परिवर्तन को चलाता है।
इन परिवर्तनों के प्रत्येक समूह में, मैं परतों को कम से कम करने के लिए सबसे अच्छे रूप में समेकित करता हूं। इसलिए यदि 4 अलग-अलग स्रोत कोड फ़ोल्डर हैं, तो वे एक एकल फ़ोल्डर के अंदर रखे जाते हैं, इसलिए इसे एकल कमांड के साथ जोड़ा जा सकता है। Apt-get जैसी किसी चीज से कोई भी पैकेज इंस्टाल हो जाता है जब पैकेज मैनेजर ओवरहेड (अपडेट और सफाई) की मात्रा को कम करने के लिए एकल RUN में विलय कर दिया जाता है।
मल्टी-स्टेज बिल्ड के लिए अपडेट:
मैं बहु-मंच निर्माण के गैर-अंतिम चरणों में छवि के आकार को कम करने के बारे में बहुत कम चिंता करता हूं। जब इन चरणों को टैग नहीं किया जाता है और अन्य नोड्स के लिए भेज दिया जाता है, तो आप प्रत्येक कमांड को एक अलग RUN
लाइन में विभाजित करके कैश पुन: उपयोग की संभावना को अधिकतम कर सकते हैं ।
हालाँकि, यह परतों को स्क्वैश करने का एक सही समाधान नहीं है क्योंकि आप चरणों के बीच कॉपी करते हैं फाइलें हैं, और बाकी छवि मेटा-डेटा जैसे पर्यावरण चर सेटिंग्स, एंट्रीपॉइंट, और कमांड नहीं। और जब आप एक लिनक्स वितरण में पैकेज स्थापित करते हैं, तो लाइब्रेरीज़ और अन्य निर्भरताएँ पूरे सिस्टम में बिखरी हो सकती हैं, जिससे सभी निर्भरताओं की एक प्रतिलिपि मुश्किल हो जाती है।
इस वजह से, मैं एक CI / CD सर्वर पर बायनेरिज़ के निर्माण के लिए एक प्रतिस्थापन के रूप में मल्टी-स्टेज बिल्ड का उपयोग करता हूं, ताकि मेरे CI / CD सर्वर को चलाने के लिए टूलिंग की आवश्यकता हो docker build
, और jdk, नोडज, गो, और न हो। कोई अन्य संकलित उपकरण स्थापित किया गया।