Foruma hoş geldin 👋, Ziyaretçi

Forum içeriğine ve tüm hizmetlerimize erişim sağlamak için foruma kayıt olmalı ya da giriş yapmalısınız. Foruma üye olmak tamamen ücretsizdir.

Docker Build'de Multi-Stage Kullanımı: Derleme ve Çalştırma Ortamlarını Ayırarak Image Boyutunu Küçültme

asteron

Üye
Katılım
14 Mart 2026
Mesajlar
7
Merhaba arkadaşlar, bugün sizlere özellikle Go, Java veya Node.js gibi derlenen/bağımlılık yönetimi yapılan uygulamalarınız için Docker imaj boyutlarınızı ciddi anlamda küçültecek, güvenliği artıracak ve en önemlisi "best practice" olan bir yöntemi anlatacağım: Multi-Stage Build.

Benim de sunucularda sıkça kullandığım bu yöntem, tek bir Dockerfile içinde birden fazla `FROM` ifadesi kullanarak, derleme işlemlerini bir "stage" (aşama) içinde yapıp, sadece çalıştırılabilir dosyayı veya runtime'ı içeren temiz bir son stage'e kopyalamamızı sağlıyor. Böylece derleme araçları, geçici dosyalar ve gereksiz bağımlılıklar nihai imajımızda yer almıyor. Hadi adım adım inceleyelim.

🎯 Multi-Stage Build'in Avantajları Neler?

Öncelikle neden böyle bir şeye ihtiyaç duyuyoruz onu konuşalım. Klasik bir Dockerfile ile uygulamanızı derleyip imaj oluşturduğunuzda, derleyici (gcc, go compiler, maven), tüm kütüphaneler ve ara dosyalar da imajın içinde kalır. Bu da;
İmaj boyutunun gereksiz yere büyümesine (bazen 1GB+),
Daha yavaş image pull/push sürelerine,
Potansiyel güvenlik açıklarına (derleyicideki bir zafiyet saldırı yüzeyini genişletir),
Daha fazla disk ve bellek kullanımına sebep olur.

Multi-Stage ile bu sorunların hepsini minimize ediyoruz. İmaj boyutlarında %80-90'a varan küçülmeler görmek mümkün.

⚙️ Temel Multi-Stage Build Yapısı

En basit haliyle iki aşamalı bir Dockerfile şöyle görünür. İlk aşama (genelde `builder` olarak isimlendirilir) derleme işini yapar. İkinci aşama ise nihai, temiz çalıştırma ortamımızdır.

Kod:
# STAGE 1: Derleme Aşaması (Builder)
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /uygulamam

# STAGE 2: Çalıştırma Aşaması (Nihai İmaj)
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
# Sadece derlenmiş binary'yi bir önceki aşamadan kopyala
COPY --from=builder /uygulamam .
EXPOSE 8080
CMD ["./uygulamam"]

Gördüğünüz gibi, ilk aşamada `golang:1.21-alpine` gibi büyük bir imaj kullandık. Ancak nihai imajımız sadece `alpine:latest` ve içine kopyaladığımız binary dosyası. `COPY --from=builder` komutu bu sihrin anahtarı. Bir önceki stage'den sadece ihtiyacımız olan dosyayı alıyoruz.

📦 Farklı Senaryolar ve Optimizasyonlar

Teknik sadece Go için değil, tüm dillerde işe yarar. İşte bir Node.js örneği:

Kod:
# STAGE 1: Bağımlılıkları Kur ve Derle
FROM node:20 AS builder
WORKDIR /app
COPY package.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# STAGE 2: Sadece Production Gereksinimleri
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

Burada dikkat etmemiz gereken nokta, `npm ci --only=production` ile sadece production bağımlılıklarını kuruyoruz. `devDependencies` nihai imaja girmiyor.

⚠️ Dikkat Edilmesi Gerekenler

Stage İsimlendirme: `AS builder` gibi isimler verirseniz, `--from=builder` ile referans vermek daha kolay ve okunabilir olur. Sayısal referans (`--from=0`) da kullanabilirsiniz ama isimlendirmek daha iyidir.
Docker Build Cache: Stage'ler birbirinden bağımsız cache'lenir. `COPY . .` gibi bir komutu mümkün olduğunca geç yapın ki dependency'ler değişmediğinde cache kırılmasın. Örnekte önce `go.mod` ve `go.sum`'ı kopyalayıp modülleri indirmemiz bu yüzden.
Çoklu Stage Kullanımı: İki stage ile sınırlı değilsiniz. Test aşaması, farklı binary'leri birleştirme gibi kompleks işler için üç veya daha fazla stage kullanabilirsiniz.
COPY --from ile Harici İmajlar: Sadece kendi stage'lerinizden değil, harici bir Docker imajından da dosya kopyalayabilirsiniz. Örneğin: `COPY --from=nginx:alpine /etc/nginx/nginx.conf /nginx.conf`

🔍 İmaj Boyutu Karşılaştırması

İşin somut faydasını görelim. Yukarıdaki Go örneğinde:
Tek Stage (geleneksel): `golang:1.21-alpine` imajı + binary ≈ 350MB
Multi-Stage: `alpine:latest` + binary ≈ 10-15MB

Aradaki fark devasa! Bu, container'ınızın daha hızlı başlaması, registry'de daha az depolama alanı ve network bandı kullanması demek.

Sonuç olarak arkadaşlar, eğer Docker imajlarınız şişmeye başladıysa, güvenlik taramasında gereksiz paketler çıkıyorsa veya deploy süreleriniz uzuyorsa, ilk bakmanız gereken noktalardan biri Multi-Stage Build'e geçiş yapmak olmalı.

Peki siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Özellikle Python veya Java gibi dillerde farklı püf noktalarınız var mı? Deneyimlerinizi ve sorularınızı aşağıya yazmaktan çekinmeyin. Hep birlikte öğrenelim.
 

Tema özelleştirme sistemi

Bu menüden forum temasının bazı alanlarını kendinize özel olarak düzenleye bilirsiniz.

Zevkine göre renk kombinasyonunu belirle

Tam ekran yada dar ekran

Temanızın gövde büyüklüğünü sevkiniz, ihtiyacınıza göre dar yada geniş olarak kulana bilirsiniz.

Geri