docker build . komutundaki o küçük nokta aslında önemli bir şey söyler: “build bağlamı (build context) bu dizindir.” Docker, build başlarken bu dizinin içeriğini build motoruna gönderir. Dizinde büyük dosyalar, node_modules ya da gizli bir .env varsa; build yavaşlar, imaj şişer ve — en kötüsü — o gizli dosya imajın içine girebilir.
Bağlam gerçekte ne kadar büyük?
Örnek bir proje düşünelim: 50 MB’lık bir veri dosyası, 20 MB’lık bir node_modules klasörü, bir .env dosyası ve küçük bir app.txt. Dockerfile ise yalnızca tüm klasörü kopyalıyor:
FROM temel-imaj
COPY . /app
BuildKit’in ayrıntılı çıktısında (--progress=plain) bağlamın boyutu görünür:
$ docker build --progress=plain -t ornek:1 .
...
#5 transferring context: 70.02MB 0.9s done
Tek satırlık uygulama için 70 MB gönderildi — ve COPY . /app bunların hepsini (gizli .env dahil) imaja yazdı. Her docker build‘da bu transfer tekrar edilir.
.dockerignore ile çözüm
Bağlam dizininin köküne .dockerignore dosyası koyun. Biçimi .gitignore‘a benzer; listelenen yollar build bağlamına hiç gönderilmez:
node_modules
*.bin
.env
.git
Aynı build’i yeniden çalıştırdığımızda:
#5 transferring context: 124B 0.0s done
$ docker run --rm ornek:2 ls -A /app
.dockerignore
Dockerfile
app.txt
70 MB’dan 124 bayta düştü; .env, node_modules ve büyük dosya imajda yok. Bu dosya aynı zamanda önbelleği de korur: ilgisiz bir dosya (örneğin bir log) değiştiğinde COPY . . katmanı gereksiz yere geçersiz kalmaz.
.dockerignore bir güvenlik önlemi olarak da düşünülmelidir: .env, *.pem, .git gibi dosyaları buraya yazmak, COPY . . ile yanlışlıkla imaja girmelerini engeller. Detay için Container Image Güvenliği yazısına bakın.
Sık kullanılan kalıplar
| Satır | Ne yapar? |
|---|---|
node_modules |
Bağımlılıkları imaj içinde npm ci ile kurduğunuz için host’taki kopyayı dışarıda bırakır |
.git |
Depo geçmişini (genellikle büyük) bağlamdan çıkarır |
*.log, tmp* |
Geçici ve log dosyaları |
.env* |
Ortam ve gizli bilgi dosyaları |
Dockerfile, .dockerignore |
İmaja girmesi gerekmeyen yapılandırma (bu dosyalar yine de build’e okunur) |
!istisna.txt |
! ile bir önceki kuralın istisnası tanımlanır |
Not: Yukarıdaki deneyde Dockerfile ve .dockerignore‘ı listeye yazmadığımız için COPY . /app bunları da imaja kopyaladı (ls çıktısındaki iki dosya). Listeye yazarsanız imaja girmezler; build motoru yine de onları build talimatları için okur.
Büyük bağlamı fark etmenin yolları
docker build --progress=plainçıktısındatransferring contextsatırına bakın; yüzlerce MB görüyorsanız bir şeyler fazla.- Build başlamadan önce uzun süre “bekliyorsa” bu çoğunlukla bağlamın gönderilmesidir, derleme değil.
- İmaj beklenenden büyükse
docker run --rm imaj ls -A /appile içine neyin girdiğine bakın.
Hızlı kontrol listesi
- Projenizin kökünde
.dockerignorevar mı? .git,node_modules, log ve.envdosyaları listede mi?COPY . .yerine mümkünse yalnızca gereken dosyaları mı kopyalıyorsunuz?transferring contextboyutu makul mü?
Sıradaki adım: build’i bir de önbellek açısından hızlandırmak için Build Cache ve BuildKit yazısına geçin. Dockerfile’ınızı otomatik kontrol etmek için sitemizdeki Dockerfile Kontrolcüsü aracını da kullanabilirsiniz.