Veri Bilimi Okulu

Python İmajları için Dockerfile Optimizasyonu
Python İmajları için Dockerfile Optimizasyonu
docker_multistage_build_960x640_kapak

Loading

Bugün sizinle Docker Docker optimizasyonu (Docker optimization), özellikle de Dockerfile optimizasyonu hakkında konuşacağız. Biliyorum, bazılarınız için özgün docker imajları yaratmak hala ürkütücü görünüyor, ama merak etmeyin, bu yazıyı okuduktan sonra tüy kadar hafif imajlar oluşturmayı, bunlardan roket hızında ayağa kalkan container yaratmayı ve bunları Fort Knox kadar güvenli hale getirmeyi öğreneceksiniz!

Neden Docker Optimizasyonu Bu Kadar Önemli?

2025’te yaşadığımız gerçek şu: Docker artık basit bir geliştirici oyuncağı değil, hem geliştirme hem de production ortamlar için olgun ve güçlü bir platform. Ama ne yazık ki çoğu geliştirici hala Docker’ı kara düzen kullanıyor. Gigabyte’larca şişmiş image’lar, yavaş deployment’lar ve güvenlik açıkları, bla bla bla!

Bir FastAPI uygulaması örneğiyle başlayalım. Basit bir “Hello World” endpoint’i olan bir uygulamamız var ve bu uygulamayı Docker’la çalıştırmak istiyoruz. İlk Dockerfile’ımız şu şekilde:

FROM ubuntu

RUN apt-get update && apt-get install -y python3 python3-pip curl

RUN pip3 install poetry

ENV PATH="/root/.local/bin:$PATH"

# Environment variables
ENV DB_PASSWORD=secret
ENV DB_USER=user
ENV DB_HOST=localhost

WORKDIR /app

COPY . /app

RUN poetry install

ENV PATH="/app/.venv/bin:$PATH"

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Bu Dockerfile’ı build ettiğimizde ne oluyor? 937 MB boyutunda bir image elde ediyoruz ve build süresi 36 saniye! Bu durum canlı ortamlarda pek kabul edilemez. Çünkü 2025 itibariyle Image boyutu: <200 MB, Build süresi: <10 saniye, Deployment: <2 dakika bir şekilde endüstri standardı. Burada yapılan en bariz hata yanlış baz imaj seçimi.

1. Doğru Base Image Seçimi (Right Base Image Selection)

Ubuntu’dan Kurtulun!

İlk ve en önemli adım: doğru base image (base image) seçimi. Ubuntu güzel bir işletim sistemi ama Docker image’ı olarak kullandığınızda gereksiz bir sürü şeyle gelir. Python uygulamanız için Ubuntu kullanmak, süpermarkete ekmek almaya kamyonla gitmek gibi!

FROM python:3.13-slim-bookworm  # Ubuntu yerine bunu kullanın!

Küçük bir base image seçmek sadece taşınabilirlik ve hızlı indirmeler sunmakla kalmaz, aynı zamanda imajınızın boyutunu küçültür ve bağımlılıklar aracılığıyla ortaya çıkan güvenlik açıklarının sayısını minimuma indirir.

İpucu: Docker Official Images tercih edin – bunlar;

✅ Uzmanlar tarafından seçilmiş
✅ Düzenli olarak gözden geçirilmiş
✅ Güvenlik açısından kontrol edilmiş
✅ Best practice’lere uygun hazırlanmış
✅ Dokümantasyonu net olan

imajlardır. Bu yüzden iyi bir başlangıç imajı olurlar.

Tag Stratejisi: “Latest” Kullanmayın!

2025’te hala latest tag’i kullanıyorsanız, lütfen durun! Latest tag’leri değişken olduğu için, belli bir süre sonra yeni bir imaja işaret edecek şekilde güncellenebilir. Bu da beklenmedik değişikliklere yol açar.

# ❌ Bunu yapmayın
FROM python:latest

# ✅ Bunu yapın
FROM python:3.13.1-slim-bookworm

2. Gereksiz Bağımlılıkları Temizleme (Removing Unnecessary Dependencies)

APT-GET Optimizasyonu

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

--no-install-recommends flag’i sadece ana bağımlılıkları yükler, önerilen paketleri değil. Ve mutlaka temizlik yapın! Bu, apt’nin yazılımları yönetmek için kullandığı paket depolarına ilişkin metadata’yı kaldırır.
Buradaki temizlik kısmı:
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

Ne temizliyor?
/var/lib/apt/lists/* → APT’nin paket listesi metadata’sı
/tmp/* → Geçici dosyalar
/var/tmp/* → Sistem geçici dosyaları

Poetry Yerine UV Kullanın

2025’te Python dependency management’da yeni bir oyuncu var: UV. Poetry’nin dependency resolver’ı oldukça yavaş olabilir, UV ise dramatik olarak hızlı!

# UV kullanarak build süresi 25 saniyeden 8.7 saniyeye düştü!
FROM python:3.13-bookworm

RUN pip install uv

COPY pyproject.toml .

RUN uv pip install --system -r pyproject.toml

3. Multi-Stage Build: Docker Optimizasyonunun Süper Kahramanı

Asıl sihir burada başlıyor! Multi-stage build’ler, Dockerfile’larınızı optimize etmeye çalışırken onları okumayı ve sürdürmeyi kolay tutmak konusunda zorluklarla karşılaşan herkes için faydalıdır. Docker 17.05 ile tanıtılan bu özellik, container dünyasında devrim yaratmış durumda. Eskiden iki ayrı Dockerfile yazmanız ya da karmaşık shell script’ler kullanmanız gereken durumlarda, artık tek bir Dockerfile ile hem build hem de runtime ortamlarınızı elegant bir şekilde ayırabiliyorsunuz. 2025’te multi-stage build kullanmamak, akıllı telefon çağında hala tuşlu telefon kullanmak gibi bir şey!

Multi-Stage Build Nedir?

Düşünün ki bir kek yapıyorsunuz. Malzemeleri karıştırmak için bir kase, pişirmek için bir fırın lazım. Ama serviste sadece kek lazım, karıştırma kasesini masada bırakmazsınız! Multi-stage build de aynı mantık.

# Build stage
FROM python:3.13-bookworm AS builder
WORKDIR /app
COPY pyproject.toml .
RUN pip install uv
RUN uv pip install --system -e .

# Production stage  
FROM python:3.13-slim-bookworm
WORKDIR /app
ENV PATH="/app/.venv/bin:$PATH"
COPY --from=builder /app/.venv /app/.venv
COPY src/ .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]

Build Stage Açıklaması:

  • FROM python:3.13-bookworm AS builder → UV’nin çalışması için gereken tam Python image’ı kullanıyoruz (curl, build tools vs. içerir)
  • WORKDIR /app → Çalışma klasörünü belirliyoruz
  • COPY pyproject.toml . → Sadece dependency dosyasını kopyalıyoruz (cache optimizasyonu için)
  • RUN pip install uv → Hızlı dependency manager UV’yi kuruyoruz
  • RUN uv pip install --system -e . → Bağımlılıkları virtual environment’a yüklüyoruz

Production Stage Açıklaması:

  • FROM python:3.13-slim-bookworm → Çok daha küçük runtime image’ına geçiyoruz
  • ENV PATH="/app/.venv/bin:$PATH" → Virtual environment’taki paketlerin bulunabilmesi için PATH ayarlıyoruz
  • COPY --from=builder /app/.venv /app/.venv → Build stage’den sadece hazır virtual environment’ı kopyalıyoruz
  • COPY src/ . → Sadece uygulama kodunu kopyalıyoruz
  • EXPOSE 8000 → Port açıyoruz
  • CMD ["uvicorn", "main:app", "--host", "0.0.0.0"] → Uygulamayı başlatıyoruz

Sonuç: Build tools final image’da yok, sadece runtime gereksinimleri var! Image boyutu 1.61 GB’dan 186 MB‘a düştü! Build süresi ise 5.3 saniye! 🚀

Multi-Stage Build’in Avantajları

Build ortamını son runtime ortamından ayırarak, image boyutunu ve saldırı yüzeyini önemli ölçüde azaltabilirsiniz. Bu, özellikle büyük build bağımlılıkları olan uygulamalar için faydalıdır.

  • %70’i geçen boyut azalması mümkün
  • 3.5x daha hızlı deployment
  • %60’ı geçebilen storage maliyet tasarrufu
  • Daha güvenli (build tool’lar canlı ortam imajında yok)

4. Akıllı Dosya Kopyalama Stratejisi

Her Şeyi Kopyalamayın!

# ❌ Kötü
COPY . .

# ✅ İyi
COPY src/ ./src/
COPY pyproject.toml ./

.dockerignore dosyası kullanarak, build context’e dahil etmek istemediğiniz yerel dosyalar hakkında açık olabilirsiniz.

.dockerignore örneği:

.git
.pytest_cache
__pycache__
*.pyc
node_modules
.env
.vscode

5. Güvenlik: Root User’dan Kaçının!

Container’ları root user olarak çalıştırmak, privilege escalation risklerini artırır. Container’lar varsayılan olarak root user olarak çalışır ve bu, bir saldırgan uygulamanızdaki bir güvenlik açığını istismar ederse, container’a root erişimi kazanabileceği anlamına gelir.

# Non-root user oluşturun
RUN adduser --disabled-password --gecos '' appuser
USER appuser

6. Secret Management: Gizli Bilgileri Güvenle Yönetmek

Environment variable’lar olarak secret geçmek 2015’te kaldı! 2025’te secret mount kullanıyoruz:

# syntax=docker/dockerfile:1
FROM python:3.13-slim-bookworm
RUN --mount=type=secret,id=db_password \
    DB_PASSWORD=$(cat /run/secrets/db_password) && \
    echo "DB_PASSWORD=$DB_PASSWORD" >> /etc/environment

Build sırasında:

docker build --secret id=db_password,src=./secrets.txt .

7. Layer Optimization: Cache’i Efektif Kullanmak

Docker’ın build cache (build cache) mekanizmasını anlayın:

# ✅ Doğru sıralama - dependencies önce
COPY pyproject.toml ./
RUN uv pip install --system -r pyproject.toml

# Sonra source code (daha sık değişir)
COPY src/ ./src/

Docker, Dockerfile’ınızdaki talimatları sırayla işler. Her talimat için Docker, build cache’den talimatı yeniden kullanıp kullanamayacağını kontrol eder.

8. Health Check: Container’ınız Gerçekten Çalışıyor mu?

HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD curl -f http://localhost:8000/health || exit 1

Health check’ler olmadan Docker, servis başarısızlıklarını tespit edemez.

9. 2025’te Yeni Trend: Distroless Images

Google’ın distroless image’ları minimal container’lar için mükemmel:

FROM gcr.io/distroless/python3-debian12
COPY --from=builder /app /app
WORKDIR /app
CMD ["python", "main.py"]

Bu image’larda shell bile yok! Güvenlik seviyesi maksimum.

10. Monitoring ve Analiz Tool’ları

Docker Image Analizi

  • Dive: Image layer’larını analiz etmek için
  • Docker Scout: Vulnerability scanning
  • Trivy: Comprehensive security scanner
# Dive ile image analizi
dive your-image:latest

# Docker Scout ile güvenlik taraması  
docker scout quickview your-image:latest

Gerçek Dünya Örneği: FastAPI Optimizasyonu

Başlangıç durumu:

  • Image boyutu: 937 MB
  • Build süresi: 36 saniye
  • Security score: Düşük

Son optimized hali:

  • Image boyutu: 124 MB (%87 azalma!)
  • Build süresi: 5.3 saniye (%85 daha hızlı!)
  • Security score: Yüksek

Final Dockerfile:

# syntax=docker/dockerfile:1

# Build stage
FROM python:3.13-bookworm AS builder
WORKDIR /app
COPY pyproject.toml ./
RUN pip install uv
RUN uv pip install --system -r pyproject.toml

# Production stage
FROM python:3.13-slim-bookworm
RUN adduser --disabled-password --gecos '' appuser
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY src/ ./src/
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s \
  CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

Sonuç: Docker Optimizasyonu Artık Zorunluluk

Modern Docker best practice’lerini benimseyerek ve multi-stage build’ler, BuildKit caching, güvenli user practice’leri ve sağlam health monitoring’i kullanarak, verimli, güvenli ve ölçeklenebilir containerize uygulamalar sağlayabilirsiniz.

2025’te Docker optimizasyonu luxury değil, necessity! Cloud native dünyada her megabyte önemli, her saniye değerli. Bu rehberdeki teknikleri uyguladığınızda:

  • Deployment süreniz %70 azalacak
  • Storage maliyetleriniz %60 düşecek
  • Security posture’ınız dramatik şekilde artacak
  • Developer experience’ınız harika olacak

Unutmayın: Docker optimizasyonu bir kez yapıp geçen iş değil, sürekli iterasyon gerektiren bir süreç. Her yeni proje için bu best practice’leri gözden geçirin, yeni tool’ları takip edin ve community’den öğrenmeye devam edin.

Şimdi gidin ve o şişman Docker image’larınızı güzel, fit ve güvenli hale getirin! Sonuçları yorumlarda paylaşmayı unutmayın. 🐳✨

Happy Dockering! 🚀

Kaynaklar

0

Bir yanıt yazın

Password Requirements:

  • At least 8 characters
  • At least 1 lowercase letter
  • At least 1 uppercase letter
  • At least 1 numerical number
  • At least 1 special character