Docker imaj boyutunu multi-stage build ve distroless ile nasıl küçültürüm?
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?
Cevap
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.
Kısa cevap
Problemin kaynağı tek: imajda olmaması gereken şeyler (derleyici, paket yöneticisi, shell) üretime sızıyor. Katmanların nasıl oluştuğunu ve .dockerignore mantığını Docker yazısında temelden anlatmıştım; buradaki optimizasyon o zeminin üstüne oturuyor.
Neden
-
Bedel iki katlı: hız ve saldırı yüzeyi. 1.2 GB’lık bir imaj her build’de upload/download süresini şişirir; taşıdığı derleyici, bash ve paket yöneticisi de üretimde hiç ihtiyaç duyulmayacak bir saldırı yüzeyi bırakır.
-
Multi-stage’in mantığı:
builderaş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=builderile al. Build araçları imaja hiç girmez. -
Go ile PHP’nin tabanı aynı yere inmez. Go binary’si kendi kendine yeter (statik linklenir), yani birkaç MB’lık bir imaj çıkar. PHP’de ise derlenmiş binary yok; PHP runtime + extension’lara ihtiyacın var, dolayısıyla hedef boyut da farklı olmak zorunda.
Ne yapmalı
-
Go için final aşamayı
scratchveyadistroless/staticyap. Distroless shell ve paket yöneticisi içermez — saldırı yüzeyi küçülür; debug gerekince:debugvaryantını kullan. -
PHP’de hedefin
php:8.x-fpm-alpineolsun. Build aşamasındacomposer install --no-devçalıştır, final aşamaya yalnızcavendor/+ uygulamayı kopyala. Yine de yüzlerce MB değil, onlu MB seviyesine inersin. -
Boyut kadar güvenliği de sıkılaştır. Konteyneri non-root çalıştır,
.dockerignoreile 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
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.