Tek bir çözüm olmadan çeşitli teknikler söz konusudur. Muhtemelen aşağıdakilerden birkaçını yapmak isteyeceksiniz:
İlk olarak, görüntü katmanlarınızı yeniden kullanmak üzere optimize edin. Önceki katmanlardan önceki katmanların önbelleğe alınma şansını artırmak için sık sık değişen adımları daha sonra Dockerfile'a koyun. Yeniden kullanılan bir katman a'da daha fazla disk alanı olarak görünecektir docker image ls
, ancak alttaki dosya sistemini incelerseniz, her katmanın yalnızca bir kopyası diskte depolanır. Bu, her biri 2 GB'lık 3 resim anlamına gelir, ancak son birkaç katmanda yalnızca 50 MB farklı olan yapı, listenin sizden beri 6 GB kullandığını göstermesine rağmen, yalnızca 2,1 GB disk alanı kaplar. yeniden kullanılan katmanların her birini iki kez sayarak.
Katman yeniden kullanımı, nadiren değişen yapı bağımlılıklarına sahip görüntüleri kodda kopyalamadan önce ilk olarak yüklediklerini görmenizdir. Şuna benzer bir desene sahip herhangi bir python örneğine bakın:
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"]
Minimum bir temel görüntü seçin. İnsanların gelen gittiğini görmek nedeni budur ubuntu
için debian:slim
(ince varyantları az araçlarla nakliye, küçüktür), hatta alpine
. Bu, başlangıç noktanızın boyutunu azaltır ve temel görüntünün sürekli yeni sürümlerini çekiyorsanız çok yardımcı olur. Ancak, temel görüntünüz nadiren değişirse katman yeniden kullanımı, minimum temel görüntünün avantajlarının çoğunu kaldırır.
Seçebileceğiniz en küçük temel görüntü scratch
, hiçbir şey, kabuk veya kitaplık değildir ve yalnızca statik olarak derlenmiş ikili dosyalarda kullanışlıdır. Aksi takdirde, çok fazla araca ihtiyaç duymadan ihtiyacınız olan araçları içeren bir temel görüntü seçin.
Daha sonra, bir dosyayı değiştiren veya silen herhangi bir adım, o dosyayı oluşturan önceki adımlarla birleştirilmelidir. Aksi takdirde, dosya izni değişikliği gibi şeylerde bile yazma üzerine kopyalama kullanan katmanlı dosya sistemi, önceki dosyadaki orijinal dosyaya sahip olur ve dosyaları kaldırdığınızda görüntü boyutu küçülmez. Bu nedenle rm
komutlarınızın sonuçta ortaya çıkan disk alanı üzerinde hiçbir etkisi yoktur. Bunun yerine, komutları aşağıdaki gibi zincirleyebilirsiniz:
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
Önkoşul her değiştiğinde aynı araç setini yeniden yüklemeniz gerektiğinden, komut zincirinin aşırı kullanılmasının yapılarınızı yavaşlatabileceğini unutmayın (örn. Wget ile alınan kod). Daha iyi bir alternatif için aşağıdaki çok aşamalı bölüme bakın.
Oluşturduğunuz görüntüde ihtiyacınız olmayan oluşturduğunuz tüm dosyalar, onu oluşturan adımda silinmelidir. Bu, paket önbelleklerini, günlükleri, man sayfalarını vb. İçerir. Her katmanda hangi dosyaların oluşturulduğunu keşfetmek için wagoodman / dive gibi bir araç kullanabilirsiniz (ki ben kişisel olarak denetlemedim ve tam kök erişimi ile çalıştığı için dikkat göstereceğim) veya barındırıcı görüntülerinizi ara kapları budanmadan oluşturup ardından farkı şununla görüntüleyebilirsiniz:
# 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
Bu ara kapların her biriyle, fark dosyaları eklenebilir, değiştirilebilir veya bu aşamada silinir neyi gösterecek (bunlar ile gösterilir A
, C
ya da D
her dosya önce). Farkı gösteren, konteynere özel yazma / yazma dosya sistemidir; bu, konteynır tarafından yazma üzerine kopyalama kullanılarak görüntü durumundan değiştirilen herhangi bir dosyadır.
Görüntü boyutunu azaltmanın en iyi yolu, derleyiciler gibi gereksiz bileşenleri gönderilen görüntünüzden kaldırmaktır. Bunun için, çok aşamalı derlemeler tek bir aşamada derlemenize izin verir ve sonra yalnızca elde edilen yapay nesneleri derleme aşamasından uygulamayı çalıştırmak için gereken minimum değere sahip bir çalışma zamanı görüntüsüne kopyalar. Bu, sonuçta elde edilen görüntü ile birlikte gönderilmedikleri için oluşturma adımlarından herhangi birini optimize etme ihtiyacını ortadan kaldırır.
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" ]
Çok aşamalı, temel görüntünüz olarak sıfırdan çalıştırabileceğiniz veya JDK gibi bir derleme ortamından JRE gibi bir çalışma süresine geçiş yapabileceğiniz statik olarak derlenmiş ikili dosyalar için idealdir. Bu, hızlı yapılara sahipken görüntü boyutunuzu önemli ölçüde azaltmanın en kolay yoludur. Önceki adımlarda oluşturulan dosyaları değiştiren veya silen adımlarınız varsa, yayın aşamanızdaki adımların zincirlenmesini yine de yapabilirsiniz, ancak çoğunlukla COPY
başka bir aşamadan, yayınlama aşamasını önceki oluşturma aşamalarında yaşanan herhangi bir katman şişmesinden yalıtır.
Not: Katmanların yeniden kullanılmasını ortadan kaldırmak pahasına bir görüntünün boyutunu küçülttüğü için görüntüleri ezmeyi önermiyorum. Bu, aynı görüntünün gelecekteki derlemelerinin güncellemeleri göndermek için daha fazla disk ve ağ trafiği gerektireceği anlamına gelir. İlk örneğe geri dönmek için, ezme resminizi 2 GB'tan 1 GB'a düşürebilir, ancak 3 GB 2,1 GB yerine 3 GB alabilir.
2.37
vs.1.47 GB