Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Docker Multistage Build Nedir?

Merhaba,

Docker yazı dizimizin bu içeriğinde image kapasitesi açısından maliyeti düşürmeyi hedefleyen ve bunun için birden fazla base image kullanılmasını gerektiren Multistage Build üzerine konuşuyor olacağız.

Multistage Build Nedir?

Multistage Build, Dockerfile dosyalarının okunabilirliğini ve bakımını kolaylaştırmak için geliştirilmiş yapılardır ve birden fazla base image kullanılması durumunu nitelemektedir.

Peki neden birden fazla base image kullanmak isteriz?
Bunun sebebi image boyutudur diyebiliriz. Oluşturduğumuz imagelerin boyutlarını lüzumsuz fazlalıklardan arındırabilmek için olabildiğince küçük tutmamız gerekmektedir. Şöyle düşünebiliriz; Dockerfile dosyasındaki her bir satır için image’de bir katman oluşturulmaktadır. Üretilen herhangi bir katmandaki ihtiyaçlar giderildikten sonra o katmanı temizlemeksizin bir sonraki katmana geçilmesi, işte o bahsedilen lüzumsuz fazlalıklara sebebiyet verecektir. Bu davranış tasarlanan Dockerfile dosyası açısından da verimsizlik örneği teşkil edecek ve boyut açısından yüksek maliyetli bir image oluşturulmasına sebep olacaktır.

Böyle bir durumda ideal bir Dockerfile dosyasını tasarlayabilmek için, uygulamayı çalıştırabilmesi için ihtiyacı dışındakilerden arındırılmış ve sadece gerekli olan dosyaları içeren bir yapıcı model geliştirilmelidir. Multistage Build mantığı Dockerfile dosyalarında birden fazla ‘FROM’ etiketi ile birden fazla base image tasarlanmasına dayanmaktadır. Her bir ‘FROM’ talimatı farklı bir katmanda değerlendirilecektir ve önceki ‘FROM’ talimatlarını ezecektir. Böylece üretilecek image’de, tüm ‘FROM’ yükünü göz ardı ederek istediğiniz bir noktada belirli çıktıları kopyalayıp esas kabul edebilirsiniz. Böylece ilgili image’in; lüzumsuz katmanlardan, o katmanların barındırdığı imagelerden arındırılmış olmasından dolayı boyutu küçülecektir.

Multistage Build Uygulanması

Multistage Build’i örneklendirebilmek için bir önceki Asp.NET Core Uygulamasını Dockerize Etmek başlıklı makalemizde oluşturduğumuz Dockerfile dosyasını ele alalım.

FROM mcr.microsoft.com/dotnet/core/sdk:3.1
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish DockerizeWebExample.csproj -c Release -o out
WORKDIR out
ENV ASPNETCORE_URLS="http://*:1453"
ENTRYPOINT ["dotnet", "DockerizeWebExample.dll"]

Bu Dockerfile dosyasında build neticesinde elde edilen image’in boyutuna bakarsak eğer;
Docker Multistage Build Nedir?

Bizler ilgili makalede basit ve içeriği dosya boyutu açısından düşük, sayısı açısından neredeyse yok denecek kadar az olan bir uygulamayı docker seviyesinde release ederek ayağa kaldırdık. Dolayısıyla böyle bir uygulama için 712 MB haddinden fazla bir kapasiteye tekabül etmektedir. Neden? Çünkü, Dockerfile içeriğindeki base image talimatına bakarsanız eğer SDK yüklü olmasından. Bizler uygulamayı release ettikten sonra üretilen image üzerinde hala SDK dosyalarını tutmaktayız. Halbuki SDK ile işimiz 5. satırdan sonra bitmekte ve o aşamada sonra Runtime’a geçmekteyiz. Haliyle bizler burada 5. satırdan sonra büyük boyutlu SDK içerisindeki Runtime’ı kullanmaktansa daha düşük boyutlu olan Asp.NET Core Runtime image’ini kullanabilir ve böylece boyutu düşürebiliriz.

Bunun için Dockerfile dosyasını aşağıdaki gibi güncelleyelim;

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 as sdkimage
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish DockerizeWebExample.csproj -c Release -o out

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
WORKDIR /app
COPY --from=sdkimage /app/out .

ENV ASPNETCORE_URLS="http://*:1453"
ENTRYPOINT ["dotnet", "DockerizeWebExample.dll"]

7. satırdaki talimata bakarsak eğer ‘FROM’ etiketiyle Asp.NET Core Runtime image’i yüklenmekte ve hemen ardından bu image içerisinde 8. satırda ‘/app’ dizini oluşturulmaktadır. Bu işlemden sonra SDK imajı içerisindeki ‘/app/out’ dizininde bulunan uygulamaya dair publish dosyalarını runtime imajına yüklememiz gerekmektedir. Bunun için 9. satırda ‘COPY’ talimatı verilmiştir. Talimatı incelersek eğer görüleceği üzere ‘–from=sdkimage’ parametresi kullanılmaktadır. Buradaki ‘sdkimage’ değeri, 1. satırdaki talimatta çekilen SDK imajına atanan aliasdan gelmektedir. Dolayısıyla ‘sdkimage’ isimli imajın içerisinde(–from) ‘/app/out’ dizinindeki dosyaları bu dizine(.) yani runtime imajında yeni açılan ‘/app’ dizinine kopyala demiş olduk.

Nihai olarak bu işlem neticesinde Dockerfile dosyasını tekrar build ederek image oluşturduğumuzda aşağıdaki görseldeki gibi boyut farkının ne kadar derin olduğunu gözlemlemekteyiz.
Docker Multistage Build Nedir.?

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

3 Cevaplar

  1. Kamil Yasin dedi ki:

    Teşekkürler

  1. 28 Mart 2020

    […] Docker Multistage Build Nedir? […]

  2. 29 Mart 2020

    […] bir önceki makalede kaleme aldığımız Multistage Build konusunda olduğu gibi .dockerignore dosyasıylada image boyutunu küçültmeyi hedeflemekte ve […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir