वे एक उदाहरण के साथ मेरे लिए सबसे अधिक समझ में आता है ...
डॉक के साथ अपने स्वयं के निर्माण की परतों की जांच करना अलग है
चलिए एक आकस्मिक उदाहरण लेते हैं Dockerfile:
FROM busybox
RUN mkdir /data
# imagine this is downloading source code
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
RUN chmod -R 0777 /data
# imagine this is compiling the app
RUN dd if=/dev/zero bs=1024 count=1024 of=/data/two
RUN chmod -R 0777 /data
# and now this cleans up that downloaded source code
RUN rm /data/one
CMD ls -alh /data
उनमें से प्रत्येक ddकमांड डिस्क में 1M फाइल को आउटपुट करता है। अस्थायी कंटेनर को बचाने के लिए एक अतिरिक्त ध्वज के साथ छवि का निर्माण करें:
docker image build --rm=false .
आउटपुट में, आप देखेंगे कि चल रहे कमांड्स में से प्रत्येक अस्थायी कंटेनर में होता है जिसे अब हम स्वचालित रूप से हटाने के बजाय रखते हैं:
...
Step 2/7 : RUN mkdir /data
---> Running in 04c5fa1360b0
---> 9b4368667b8c
Step 3/7 : RUN dd if=/dev/zero bs=1024 count=1024 of=/data/one
---> Running in f1b72db3bfaa
1024+0 records in
1024+0 records out
1048576 bytes (1.0MB) copied, 0.006002 seconds, 166.6MB/s
---> ea2506fc6e11
यदि आप docker diffउन कंटेनर आईडी में से प्रत्येक पर चलते हैं , तो आप देखेंगे कि उन कंटेनरों में क्या फाइलें बनाई गई थीं:
$ docker diff 04c5fa1360b0 # mkdir /data
A /data
$ docker diff f1b72db3bfaa # dd if=/dev/zero bs=1024 count=1024 of=/data/one
C /data
A /data/one
$ docker diff 81c607555a7d # chmod -R 0777 /data
C /data
C /data/one
$ docker diff 1bd249e1a47b # dd if=/dev/zero bs=1024 count=1024 of=/data/two
C /data
A /data/two
$ docker diff 038bd2bc5aea # chmod -R 0777 /data
C /data/one
C /data/two
$ docker diff 504c6e9b6637 # rm /data/one
C /data
D /data/one
एक Aफ़ाइल के साथ उपसर्ग की गई प्रत्येक पंक्ति फ़ाइल को जोड़ रही है, Cएक मौजूदा फ़ाइल में परिवर्तन को इंगित करती है, और Dएक डिलीट को इंगित करती है।
यहाँ TL, DR हिस्सा है
इनमें से प्रत्येक कंटेनर फाइलसिस्टम ऊपर भिन्न होता है, एक "परत" में जाता है जो कि एक कंटेनर के रूप में छवि को चलाने पर इकट्ठा हो जाता है। ऐड या चेंज होने पर पूरी फाइल प्रत्येक लेयर में होती है, इसलिए उनमें से प्रत्येक chmodकमांड केवल अनुमति बिट को बदलने के बावजूद पूरी फाइल को अगली लेयर में कॉपी किया जाता है। हटाए गए / डेटा / एक फ़ाइल अभी भी पिछली परतों में है, वास्तव में 3 बार, और नेटवर्क पर कॉपी की जाएगी और जब आप छवि को खींचते हैं तो डिस्क पर संग्रहीत होता है।
मौजूदा छवियों की जांच
आप docker historyकमांड के साथ मौजूदा छवि की परतों को बनाने में जाने वाले कमांड देख सकते हैं । आप docker image inspectएक छवि पर भी चला सकते हैं और रूटएफएस अनुभाग के तहत परतों की सूची देख सकते हैं।
यहाँ उपरोक्त छवि के लिए इतिहास है:
IMAGE CREATED CREATED BY SIZE COMMENT
a81cfb93008c 4 seconds ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "ls -… 0B
f36265598aef 5 seconds ago /bin/sh -c rm /data/one 0B
c79aff033b1c 7 seconds ago /bin/sh -c chmod -R 0777 /data 2.1MB
b821dfe9ea38 10 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
a5602b8e8c69 13 seconds ago /bin/sh -c chmod -R 0777 /data 1.05MB
08ec3c707b11 15 seconds ago /bin/sh -c dd if=/dev/zero bs=1024 count=102… 1.05MB
ed27832cb6c7 18 seconds ago /bin/sh -c mkdir /data 0B
22c2dd5ee85d 2 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0B
<missing> 2 weeks ago /bin/sh -c #(nop) ADD file:2a4c44bdcb743a52f… 1.16MB
नवीनतम परतें शीर्ष पर सूचीबद्ध हैं। ध्यान दें, नीचे दो परतें हैं जो काफी पुरानी हैं। वे बिजीबॉक्स इमेज से ही आते हैं। जब आप एक छवि बनाते हैं, तो आप FROMपंक्ति में निर्दिष्ट छवि की सभी परतों को प्राप्त करते हैं । CMDलाइन की तरह छवि मेटा-डेटा में बदलाव के लिए भी परतें जोड़ी जा रही हैं । वे मुश्किल से किसी भी स्थान को लेते हैं और रिकॉर्ड के लिए अधिक होते हैं जो आपके द्वारा चलाए जा रहे चित्र पर लागू होते हैं।
क्यों परतें?
परतों के कुछ फायदे हैं। सबसे पहले, वे अपरिवर्तनीय हैं। एक बार बना लेने के बाद, sha256 हैश द्वारा पहचानी गई वह परत कभी नहीं बदलेगी। यह अपरिवर्तनीयता छवियों को सुरक्षित रूप से एक-दूसरे को बनाने और बंद करने की अनुमति देती है। यदि दो डॉकफाइल्स में लाइनों का एक ही प्रारंभिक सेट होता है, और एक ही सर्वर पर बनाया जाता है, तो वे प्रारंभिक परतों के समान सेट को साझा करेंगे, जिससे डिस्क स्थान की बचत होगी। इसका मतलब यह भी है कि यदि आप किसी छवि को फिर से बनाते हैं, तो डॉकफर्इल की अंतिम कुछ पंक्तियों के साथ बदलावों का सामना करना पड़ता है, केवल उन परतों को फिर से बनाने की आवश्यकता होती है और बाकी को परत कैश से पुन: उपयोग किया जा सकता है। यह बहुत तेजी से docker की छवियों का पुनर्निर्माण कर सकता है।
एक कंटेनर के अंदर, आप छवि फाइलसिस्टम देखते हैं, लेकिन उस फाइलसिस्टम की नकल नहीं की जाती है। उन इमेज लेयर्स के शीर्ष पर, कंटेनर माउंट करता है, जो स्वयं रीड-राइट फाइलसिस्टम लेयर है। किसी फ़ाइल का हर रीड लेयर्स से तब तक नीचे जाता है जब तक कि वह उस लेयर को हिट नहीं कर देता है, जिसने डिलीट करने के लिए फाइल को चिन्हित किया है, उस लेयर में फाइल की एक कॉपी होती है, या रीड लेयर्स के माध्यम से सर्च करने के लिए रन आउट हो जाती है। हर लेखन कंटेनर विशिष्ट रीड-राइट परत में एक संशोधन करता है।
परत ब्लोट को कम करना
परतों के नीचे एक ऐसी छवियां बन रही हैं, जो फ़ाइलों या शिप फ़ाइलों की नकल करती हैं, जिन्हें बाद की परत में हटा दिया जाता है। समाधान अक्सर एक कमांड में कई कमांड को मर्ज करने के लिए होता है RUN। विशेष रूप से जब आप मौजूदा फ़ाइलों को संशोधित कर रहे हैं या फ़ाइलों को हटा रहे हैं, तो आप उन चरणों को उसी कमांड में चलाना चाहते हैं जहां वे पहली बार बनाए गए थे। उपरोक्त डॉकरीफाइल का पुनर्लेखन इस तरह दिखेगा:
FROM busybox
RUN mkdir /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/one \
&& chmod -R 0777 /data \
&& dd if=/dev/zero bs=1024 count=1024 of=/data/two \
&& chmod -R 0777 /data \
&& rm /data/one
CMD ls -alh /data
और यदि आप परिणामी छवियों की तुलना करते हैं:
- बिजीबॉक्स: ~ 1 एमबी
- पहली छवि: ~ 6 एमबी
- दूसरी छवि: ~ 2 एमबी
बस एक साथ कुछ पंक्तियों को मर्ज किए गए उदाहरण में मिलाते हुए, हमें अपनी छवि में समान परिणामी सामग्री मिली, और हमारी छवि को 5MB से सिकोड़कर केवल 1MB फ़ाइल है जो आप अंतिम छवि में देखते हैं।