Bir örnekle bana en mantıklı ...
Docker diff ile kendi yapınızın katmanlarını inceleme
Dockerfile için örnek bir örnek alalım:
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
Bu dd
komutların her biri diske 1M dosyası verir. Geçici kapsayıcıları kaydetmek için görüntüyü fazladan bir bayrakla oluşturalım:
docker image build --rm=false .
Çıktıda, çalışan komutların her birinin şimdi otomatik olarak silmek yerine tuttuğumuz geçici bir kapta gerçekleştiğini göreceksiniz:
...
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
Bu kapsayıcı kimliklerinin her birinde a çalıştırırsanız , bu kapsayıcılarda hangi dosyaların oluşturulduğunu görürsünüz:
$ 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
Ön ekine sahip her satır A
dosyayı ekler, var olan bir dosyada yapılan C
değişikliği ve D
bir silme işlemini belirtir.
İşte TL; DR kısmı
Bu kapsayıcı dosya sistemi farklarının her biri, görüntüyü kapsayıcı olarak çalıştırdığınızda birleştirilen bir "katmana" gider. Bir ekleme veya değiştirme olduğunda tüm dosya her katmandadır, bu nedenle bu chmod
komutların her biri, bir izin bitini değiştirmesine rağmen, tüm dosyanın bir sonraki katmana kopyalanmasına neden olur. Silinen / veri / bir dosya, önceki katmanlarda, aslında 3 kez ve görüntüyü çektiğinizde ağ üzerinden kopyalanacak ve diskte saklanacaktır.
Mevcut görüntüleri inceleme
Komutla mevcut bir görüntünün katmanlarını oluşturmaya giden komutları görebilirsiniz docker history
. Ayrıca docker image inspect
bir görüntü üzerinde a çalıştırabilir ve RootFS bölümünün altındaki katmanların listesini görebilirsiniz.
Yukarıdaki resim için tarih:
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
En yeni katmanlar üstte listelenir. Dikkat çeken, altta oldukça eski olan iki katman var. Meşgul kutusu görüntüsünün kendisinden geliyorlar. Bir görüntü oluşturduğunuzda, FROM
satırda belirttiğiniz görüntünün tüm katmanlarını devralırsınız . Görüntü meta verilerindeki, CMD
çizgi gibi değişiklikler için eklenen katmanlar da vardır . Çok az yer kaplarlar ve çalıştırdığınız görüntü için hangi ayarların geçerli olduğunu kaydetmek için daha fazladır.
Neden katmanlar?
Katmanların birkaç avantajı vardır. İlk olarak değişmezler. Bir kez oluşturulduktan sonra, sha256 karmasıyla tanımlanan katman asla değişmez. Bu değişmezlik, görüntülerin birbirinden güvenli bir şekilde oluşturulmasını ve çatallanmasını sağlar. İki docker dosyası aynı ilk satır kümesine sahipse ve aynı sunucu üzerinde oluşturulmuşsa, disk alanından tasarruf ederek aynı başlangıç katmanları kümesini paylaşırlar. Bu, Dockerfile'ın yalnızca son birkaç satırında değişikliklerle birlikte bir görüntüyü yeniden oluşturduğunuzda, yalnızca bu katmanların yeniden oluşturulması ve geri kalanı katman önbelleğinden yeniden kullanılabileceği anlamına gelir. Bu, docker görüntülerinin yeniden oluşturulmasını çok hızlı hale getirebilir.
Bir kabın içinde görüntü dosya sistemini görürsünüz, ancak bu dosya sistemi kopyalanmaz. Bu görüntü katmanlarının üstünde, kap kendi okuma-yazma dosya sistemi katmanını bağlar. Bir dosyanın her okunması, dosyayı silinmek üzere işaretlenmiş bir katmana çarpana kadar, o katmanda dosyanın bir kopyasına sahip olana veya okunacak arama katmanları bitene kadar katmanlar arasında ilerler. Her yazma, konteynere özgü okuma-yazma katmanında bir değişiklik yapar.
Katman şişkinliğini azaltma
Katmanların bir dezavantajı, dosyaları çoğaltan veya daha sonraki bir katmanda silinen dosyaları gönderen görüntüler oluşturmaktır. Çözüm genellikle birden çok komutu tek bir RUN
komutta birleştirmektir . Özellikle mevcut dosyaları değiştirirken veya dosyaları silerken, bu adımların ilk oluşturuldukları komutla çalışmasını istersiniz. Yukarıdaki Dockerfile'ın yeniden yazılması şöyle görünür:
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
Ve ortaya çıkan görüntüleri karşılaştırırsanız:
- meşgul kutusu: ~ 1MB
- ilk resim: ~ 6MB
- ikinci resim: ~ 2MB
Anlaşılan örnekte bazı satırları birleştirerek, görüntümüzde elde edilen aynı içeriği aldık ve görüntümüzü 5MB'den son görüntüde gördüğünüz 1MB dosyasına küçülttük.