# Docker imaj boyutunu multi-stage build ve distroless ile nasıl küçültürüm?

> Build araçlarını builder aşamasında bırakın: final aşama Go için distroless ya da scratch, PHP için fpm-alpine olsun; container'ı non-root çalıştırın.

- Soruldu: 2026-06-11
- Yanıtlandı: 2026-06-12
- Soran: Korhan
- Etiketler: ci-cd, docker, altyapi
- Kaynak: https://www.muhammetsafak.com.tr/sor-bakalim/docker-imaj-boyutunu-multi-stage-ve-distroless-ile-kucultmek/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
**Soru:** Üretime gönderdiğimiz Go veya PHP Docker imajları 1.2 GB'ı buluyor. Bu hem CI/CD'yi yavaşlatıyor (upload/download) hem de imajda gereksiz derleyici, bash gibi kütüphaneler olduğu için saldırı yüzeyi yaratıyor.

Multi-stage build ile derleme araçlarını ilk aşamada bırakıp üretime sadece distroless veya alpine tabanlı minimal (mesela 50 MB) bir imaj çıkarmayı nasıl sağlarım?


Kısa cevap: 1.2 GB imaj, tüm build toolchain'ini üretime taşıyor — hem yavaş hem de geniş bir saldırı yüzeyi. Multi-stage build ikisini birden çözer; final aşamaya sadece artefaktı ve runtime'ı koyarsın.

Problemin kaynağı tek: imajda olmaması gereken şeyler (derleyici, paket yöneticisi, shell) üretime sızıyor.

1. **Multi-stage'in mantığı: `builder` aşaması üretir, final aşaması sadece kopyalar.** İlk aşamaya derleyiciyi ve bağımlılıkları koy, artefaktı üret. Final aşamaya yalnızca binary/uygulama + çalışması için gereken runtime'ı `COPY --from=builder` ile al. Build araçları imaja hiç girmez.
2. **Go için final aşama `scratch` veya `distroless/static` olabilir.** Go binary'si kendi kendine yeter (statik linklenir), yani birkaç MB'lık bir imaj çıkar. Distroless shell ve paket yöneticisi içermez — saldırı yüzeyi küçülür; debug gerekince `:debug` varyantını kullan.
3. **PHP biraz daha nüanslı: runtime kaçınılmaz.** PHP'de derlenmiş binary yok; PHP runtime + extension'lara ihtiyacın var. Hedefin `php:8.x-fpm-alpine`; build aşamasında `composer install --no-dev` çalıştır, final aşamaya yalnızca `vendor/` + uygulamayı kopyala. Yine de yüzlerce MB değil, onlu MB seviyesine inersin.
4. **Boyut kadar güvenlik de önemli.** Konteyneri **non-root** çalıştır, `.dockerignore` ile gereksiz dosyaları dışla, base imajı digest ile pinle, bağımlılık aşamasını registry layer cache'ine bıraktır ki her build'de yeniden çekilmesin.

**Sonuç:** Ben olsam multi-stage + Go'da `distroless/static`/`scratch`, PHP'de `fpm-alpine` kullanır; non-root çalışır ve `.dockerignore`'u sıkı tutardım. 1.2 GB'lık imaj böylece onlu MB seviyesine iner — CI/CD hızlanır, saldırı yüzeyi daralır. İmaj katmanlarının nasıl çalıştığını ve `.dockerignore` mantığını hub yazısında temelden anlattım; oradaki kurulum bu optimizasyonun zeminini oturtur.

## İlgili Yazılar

- [Docker sanallaştırma: kurulum ve temel kullanım](/blog/docker-sanallastirma-teknolojisi-kurulum-kullanim/) — Blog
- [CI/CD'de OIDC ve IAM Role ile şifresiz (secretless) AWS erişimini nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/ci-cd-de-secret-yonetimi-ve-oidc-ile-sifresiz-erisim/) — Sor Bakalım
- [Self-hosted CI/CD runner'larını nasıl izole eder, her çalışmadan sonra temizlenen (ephemeral) ortamı nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/self-hosted-ci-cd-runner-izolasyonu-ve-ephemeral-ortam/) — Sor Bakalım
- [Terraform state'i S3 + DynamoDB locking ile nasıl güvenli yönetirim?](https://www.muhammetsafak.com.tr/sor-bakalim/terraform-state-yonetimi-s3-ve-dynamodb-ile-locking/) — Sor Bakalım
