Dockerfile Projeye En Doğru Şekilde Ekleme Rehberi [2026]

Dockerfile Projeye En Doğru Şekilde Ekleme Rehberi [2026] - Kapak Görseli

Docker imajın bir türlü küçülmüyor, build süresi uzuyor ya da production’a çıkan konteyner ilk güvenlik taramasında kırmızı bayrak kaldırıyorsa sorun çoğu zaman Dockerfile dosyasını projeye ekleme biçiminde başlar. Doğru konum, doğru katman sırası, doğru base image ve doğru kopyalama stratejisi; performans, güvenlik ve bakım maliyetini doğrudan etkiler. Bu rehberde Dockerfile’ı projene en doğru şekilde nasıl yerleştireceğini, neden öyle yapman gerektiğini ve sahada gerçekten işe yarayan uygulamaları net örneklerle anlatacağım.

Dockerfile projeye eklerken önce hangi mantığı kurman gerekir

Dockerfile, konteyner imajının tarifidir. Ama onu sadece “çalıştırma dosyası” gibi görmek hata yaratır. Asıl işlevi, projenin derlenme, paketlenme ve çalıştırılma düzenini tekrar üretilebilir hale getirmektir. Yani senin makinede çalışan uygulamanın CI ortamında, test aşamasında ve production sunucusunda aynı davranışı vermesini sağlar.

Burada ilk kritik nokta şudur: Dockerfile tek başına iyi ya da kötü değildir. Onu nereye koyduğun, hangi dosyalarla birlikte çalıştırdığın ve build context’i nasıl yönettiğin kaliteyi belirler.

Docker ekibi uzun süredir Dockerfile tasarımında küçük, güvenli ve tekrar üretilebilir imaj yaklaşımını öne çıkarıyor. Özellikle resmi Docker dokümantasyonu, gereksiz bağımlılıkları azaltmayı, katman önbelleğini verimli kullanmayı ve tek sorumluluk mantığını savunur. Bu yaklaşım rastgele bir tercih değil. CNCF ekosisteminde konteyner temelli dağıtımın büyümesiyle birlikte ekipler, imaj boyutu ve güvenlik açığı sayısı arasında çok net bir ilişki gördü. Daha büyük imaj, çoğu zaman daha fazla paket ve daha geniş saldırı yüzeyi demektir.

Kendi tecrübemle söyleyebilirim ki ekiplerin en sık düştüğü hata, Dockerfile’ı proje sonunda “bir de bunu ekleyelim” mantığıyla oluşturmalarıdır. Oysa Dockerfile, projenin teslim zincirinin bir parçasıdır. Başta planlarsan daha temiz bir yapı kurarsın.

Dockerfile projede çoğu zaman kök dizinde yer alır. Bunun temel sebebi, build context yönetimini kolaylaştırmasıdır. Sen docker build komutunu proje kökünde çalıştırdığında uygulama dosyalarına, lock dosyalarına, konfigürasyonlara ve .dockerignore dosyasına tek noktadan erişirsin. Bu yapı hem okunabilirliği artırır hem de CI süreçlerinde standartlaşma sağlar.

Dockerfile projeye en doğru şekilde nasıl eklenir

Doğru ekleme sürecini sadece dosya oluşturmak gibi düşünme. Bu iş, dizin yapısı, bağımlılık yönetimi, cache sırası, güvenlik ve çalışma şeklinin birlikte tasarlanmasını ister.

1. Dockerfile dosyasını proje kök dizinine yerleştir

En yaygın ve doğru yaklaşım, Dockerfile dosyasını repository köküne koymaktır. Çünkü:
– docker build . komutu en sade haliyle çalışır
– CI araçları varsayılan olarak bu düzeni daha kolay algılar
– .dockerignore aynı seviyede durduğu için build context kontrolü kolaylaşır
– Takım arkadaşların dosyayı aramak zorunda kalmaz

İstisna yok mu? Elbette var. Monorepo yapısında her servis için ayrı dizin kullanıyorsan her servisin kendi Dockerfile dosyası ilgili servis klasöründe bulunabilir. Ama bu durumda build context’i dikkatle yönetmen gerekir. Aksi halde yanlış klasörden gereksiz dosya taşırsın.

Örnek yapı:

project-root/
Dockerfile
.dockerignore
package.json
package-lock.json
src/

Bu yapı özellikle tek servisli Node.js, Python, Go ve PHP projelerinde düzenli çalışır.

2. Önce bağımlılık dosyalarını kopyala, sonra kaynak kodu ekle

Docker katman önbelleği burada oyunun kaderini değiştirir. Eğer önce tüm proje dosyalarını kopyalarsan en ufak kod değişikliğinde bağımlılık katmanı da yeniden kurulur. Bu da build süresini uzatır.

Node.js örneği:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci –only=production
COPY . .
CMD [“node”, “server.js”]

Bu sırada mantık şu:
– package.json ve lock dosyası değişmezse npm ci katmanı cache’den gelir
– Sadece uygulama kodu değişirse bağımlılıklar yeniden kurulmaz

Google Cloud ve Docker topluluğunda yayınlanan pek çok teknik içerik, katman cache stratejisinin CI sürelerini hissedilir biçimde düşürdüğünü gösteriyor. Büyük ekiplerde dakikalarca süren build farkı, ay sonunda ciddi maliyet demektir.

Yıllar süren container süreçleri takibim gösteriyor ki yanlış COPY sırası, küçük ekiplerde bile teslim hızını fark edilir düzeyde yavaşlatıyor.

3. .dockerignore dosyasını Dockerfile ile birlikte oluştur

Dockerfile ekleyip .dockerignore eklememek, evin kapısını kilitleyip pencereleri açık bırakmaya benzer. Çünkü build context içine gereksiz dosyalar girerse:
– Build süresi uzar
– İmaj şişer
– Gizli dosyalar yanlışlıkla imaja taşınabilir
– nodemodules, log, .git gibi klasörler gereksiz yük oluşturur

Örnek .dockerignore içeriği:

nodemodules
.git
.env
coverage
dist
npm-debug.log

Özellikle .env dosyasını build context dışında tutmak gerekir. Hassas veriyi imaja gömmek en yaygın güvenlik hatalarından biridir. OWASP’in container güvenlik önerileri de sırların imaj içinde tutulmamasını açık biçimde destekler.

4. Base image seçimini küçüklük değil uygunluk üzerinden yap

Birçok kişi alpine gördüğünde otomatik olarak “en iyi seçim” sanır. Bu doğru değil. Alpine küçüktür ama musl libc kullandığı için bazı binary bağımlılıkları ve native modüllerde uyumluluk sorunları çıkarabilir. Debian slim tabanlı görseller bazı projelerde daha dengeli sonuç verir.

Seçim yaparken şu soruları sor:
– Uygulaman native paket derliyor mu
– Güvenlik tarayıcın hangi taban imajlarda daha temiz sonuç veriyor
– Build süresinde mi kazanmak istiyorsun, runtime uyumluluğunda mı
– Ekip bu imajı sürdürebilecek mi

Snyk ve benzeri güvenlik tarama platformlarının yıllık raporlarında, taban imaj seçiminin açık sayısını doğrudan etkilediği sıkça vurgulanır. Daha az paket içeren imajlar çoğu zaman daha düşük risk taşır. Ama uyumsuz küçük imaj, seni geçici hack çözümlerine iter ve uzun vadede daha büyük sorun çıkarır.

5. Multi-stage build kullanarak final imajı sade tut

Derleme için gereken araçları çalışma anındaki imaja koymak büyük hatadır. Multi-stage build bu sorunu çözer.

Örnek:

FROM golang:1.24 AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

FROM alpine:3.20
WORKDIR /app
COPY –from=builder /src/app .
CMD [“./app”]

Burada ilk aşama derleme yapar. İkinci aşama sadece çalıştırma için gereken binary’yi alır. Böylece:
– İmaj küçülür
– Saldırı yüzeyi daralır
– Deploy süresi iyileşir
– Registry depolama maliyeti azalır

Bu yöntem özellikle Go, Java, Node.js frontend build, Rust ve .NET projelerinde çok verimlidir.

6. Uygulamayı root kullanıcıyla çalıştırma

Konteyner içinde root olmak, risk alanını büyütür. Mümkünse özel bir kullanıcı oluştur ve uygulamayı o kullanıcıyla başlat.

Örnek:

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

NIST ve OWASP yayınlarında least privilege yaklaşımı uzun süredir temel güvenlik ilkesi olarak yer alır. Konteyner içinde de aynı mantık geçerlidir. Root ile çalışan uygulama, yanlış konfigürasyon durumunda hasarı büyütebilir.

7. Tek Dockerfile yetmiyorsa isimlendirmeyi açık yap

Bazı projelerde geliştirme, test ve production için farklı Dockerfile sürümleri gerekir. Böyle durumlarda isimlendirmeyi açık yap:
– Dockerfile
– Dockerfile.dev
– Dockerfile.test

Ama gereksiz çoğaltma yapma. Fark küçükse build arg veya compose profilleri daha temiz çözüm sunar. Aksi halde bakım yükü artar.

8. Dockerfile içine sır yazma

API key, veritabanı şifresi, özel token gibi verileri ENV satırıyla sabitlemek büyük risktir. Çünkü imaj katman geçmişi bu bilgiyi taşıyabilir. Bunun yerine:
– Runtime environment variable kullan
– Secret manager kullan
– CI secret store kullan

Bilim Türk üzerinde teknik yayın hazırlarken en çok altını çizdiğim noktalardan biri de bu: geliştiriciler çoğu zaman hız uğruna sır yönetimini ikinci plana atıyor. Oysa bu hata, performans sorunundan daha pahalıya patlar.

Farklı proje türlerinde doğru Dockerfile yerleşimi

Her teknoloji aynı yapıyı istemez. Bu yüzden dosya konumunu ve içeriğini proje tipine göre düşünmek gerekir.

Node.js backend projesi

En doğru yer çoğu zaman kök dizindir. package.json, lock dosyası ve kaynak kod aynı bağlamda durur. Eğer TypeScript kullanıyorsan build ve runtime için multi-stage yaklaşım daha iyi sonuç verir.

Örnek akış:
– Builder aşamasında npm ci
– TypeScript derleme
– Final aşamada sadece dist ve production dependency taşı

Python projesi

requirements.txt ya da pyproject.toml dosyası kökteyse Dockerfile da kökte dursun. Sanal ortam mantığını konteyner içine taşımak yerine sistematik katman yapısı kur. Özellikle data science projelerinde gereksiz notebook ve büyük veri dosyalarını .dockerignore ile dışarıda tut.

Java projesi

Maven ya da Gradle kullanılan projelerde multi-stage neredeyse standarttır. İlk aşamada build al, ikinci aşamada sadece jar dosyasını taşı. JDK yerine çoğu zaman JRE tabanlı final imaj daha doğru seçim olur.

Monorepo yapısı

Burada iki yaklaşım öne çıkar:
– Her servis klasöründe ayrı Dockerfile
– Kök dizinde merkezi build mantığı

Servislerin bağımsız dağıtıldığı yapılarda ilk yöntem daha temizdir. Ama ortak kütüphaneler kullanıyorsan build context’i daraltmak için komut seviyesinde dikkatli davranman gerekir. Aksi halde gereksiz dosya transferi yaşarsın.

Sahada en çok gördüğüm hatalar ve bunların gerçek etkisi

Dockerfile ekleme aşamasında yapılan küçük gibi görünen hatalar, ileride ciddi teknik borç üretir.

En sık gördüğüm hatalar:
– Dockerfile’ı src klasörüne koyup build context’i karmaşık hale getirmek
– .dockerignore yazmamak
– COPY . . satırını çok erken kullanmak
– latest etiketiyle taban imaj sabitlememek
– Geliştirme araçlarını production imajda bırakmak
– Root kullanıcıyla çalıştırmak
Sırları Dockerfile içine yazmak

Kendi tecrübemle söyleyebilirim ki özellikle latest etiketi ekip içinde görünmeyen kırılmalara yol açar. Dün çalışan imaj bugün farklı paket sürümüyle gelir ve hata ayıklama süresi uzar. Bu yüzden mümkün olduğunda sürüm pinleme yap.

Tarihsel olarak da sektör bu noktaya deneyimle geldi. İlk konteynerleşme dönemlerinde ekipler “çalışıyorsa yeter” mantığıyla büyük ve dağınık imajlar üretiyordu. Kubernetes ve CI/CD yaygınlaştıkça tekrar üretilebilirlik, güvenlik taraması ve hızlı rollback ihtiyacı arttı. Bu da Dockerfile kalitesini doğrudan operasyon kalitesine bağladı.

Bilim Türk okurları için burada net bir çerçeve sunmak isterim: iyi Dockerfile, sadece yazılımı ayağa kaldıran dosya değildir; ekibin hızını, güvenliğini ve sürdürülebilirliğini belirleyen teknik sözleşmedir.

Projene ekledikten sonra Dockerfile kalitesini nasıl test edersin

Dockerfile dosyasını eklemek işin yarısıdır. Doğru eklediğini doğrulaman gerekir.

Şu kontrolleri yap:
1. docker build komutu temiz ortamda hatasız çalışıyor mu
2. İmaj boyutu beklediğinden büyük mü
3. docker history çıktısında gereksiz katman var mı
4. Güvenlik tarayıcısı yüksek riskli paket gösteriyor mu
5. Uygulama non-root kullanıcıyla açılıyor mu
6. .env ya da gizli dosya imaja sızmış mı
7. Kod değişmediğinde bağımlılık katmanı cache’den geliyor mu

Ek olarak hadolint gibi araçlar Dockerfile kalitesini otomatik denetler. Trivy, Grype ya da Snyk gibi araçlar da güvenlik açığı taraması için güçlü destek verir. Tek bir araç her şeyi çözmez ama birlikte kullanıldığında çok sağlam kontrol hattı kurarsın.

Sıkça Sorulan Sorular

Dockerfile mutlaka proje kök dizininde mi olmalı?

Hayır, ama çoğu projede en temiz ve yönetilebilir yer kök dizindir. Monorepo gibi özel yapılarda servis klasörü daha mantıklı olabilir.

.dockerignore olmadan Dockerfile kullanabilir miyim?

Kullanırsın ama gereksiz dosyaları build context içine alırsın. Bu da hız, güvenlik ve imaj boyutu açısından zarar verir.

Tek projede birden fazla Dockerfile kullanmak doğru mu?

Evet, geliştirme ve production ihtiyaçları çok farklıysa doğru olabilir. Yine de önce tek dosyada çözüm üretebilir misin diye bak.

Alpine tabanlı imaj her zaman daha mı iyidir?

Hayır. Küçük olması avantajdır ama her projede uyumluluk sağlamaz. Native bağımlılıklarda sorun çıkarabilir.

Dockerfile içine ENV ile şifre yazmak neden riskli?

Çünkü imaj katmanları ve geçmiş kayıtları bu veriyi taşıyabilir. Secret yönetimini runtime tarafında kurmak daha güvenlidir.

Multi-stage build küçük projelerde de gerekli mi?

Her zaman şart değil ama build araçlarını final imajdan ayırmak istiyorsan küçük projede bile fayda sağlar.

En çok zorlandığın kısım Dockerfile’ın nereye konacağı mı, yoksa içeriğin nasıl sıralanacağı mı? Kullandığın proje yapısını yorumlarda paylaş, birlikte en doğru dizilimi çıkaralım.

Continue Reading