- Dockerfile nedir ve hangi sorunu çözer?
- Temel talimatlar ve ilk Dockerfile
- Katman önbelleği: talimat sırası derleme hızını belirler
- Çok aşamalı derleme (multi-stage build)
- Taban imaj, güvenlik ve .dockerignore
- CMD, ENTRYPOINT ve sinyaller
- Sık yapılan hatalar ve kontrol listesi
- Mindset programlarında nerede çalışılır?
- Sık sorulan sorular
Dockerfile yazma rehberi: talimatlar, önbellek ve çok aşamalı derleme
Dockerfile yazmanın adımları: FROM, COPY, RUN ve CMD komutları, katman önbelleği, çok aşamalı derleme, .dockerignore ve güvenlik için önerilen uygulamalar.
Dockerfile nedir ve hangi sorunu çözer?
Dockerfile, bir Docker imajının nasıl oluşturulacağını adım adım tarif eden metin dosyasıdır. Dosyadaki her talimat imajda bir katman üretir: hangi taban imajdan başlanacağı, hangi dosyaların kopyalanacağı, hangi komutların çalıştırılacağı ve konteyner ayağa kalktığında hangi sürecin başlayacağı burada yazılır. Aynı Dockerfile, farklı makinelerde aynı imajı üretir; "bende çalışıyordu" sorununu azaltan şey budur.
İyi yazılmış bir Dockerfile şunları sağlar: küçük ve güvenli bir imaj, hızlı yeniden derleme ve okunabilir bir tarif. Kötü yazılmış olan ise gereksiz boyut, tekrarlanan indirmeler, imajın içinde kalan gizli bilgiler ve root olarak çalışan bir uygulama anlamına gelir.
Temel talimatlar ve ilk Dockerfile
Başlıca talimatlar şunlardır:
- FROM: Başlangıç imajını belirler. Her Dockerfile bununla başlar.
- WORKDIR: Sonraki talimatların çalışacağı dizini ayarlar. Docker belgeleri, RUN cd yerine WORKDIR kullanmayı ve mutlak yol vermeyi önerir.
- COPY: Dosyaları derleme bağlamından imaja kopyalar. Çoğu durumda ADD yerine COPY tercih edilir.
- RUN: Derleme sırasında komut çalıştırır, örneğin bağımlılık kurar.
- ENV ve ARG: ENV imajda ve konteynerde kalıcı değişken tanımlar. ARG yalnızca derleme sırasında geçerlidir ve son imajda kalmaz.
- EXPOSE: Uygulamanın dinlediği portu belgeler.
- USER: Sonraki talimatları ve çalışan süreci hangi kullanıcının yürüteceğini belirler.
- CMD ve ENTRYPOINT: Konteyner başlayınca çalışacak komutu belirler.
Örnek olarak bir Node uygulamasının ilk Dockerfile'ı:
FROM node:<sürüm>-alpine WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . EXPOSE <port> CMD ["node", "server.js"]
İmajı derlemek için: docker build -t uygulamam .
Bağımlılık dosyaları kaynak kodundan önce kopyalanır. Bu sıralama bir tesadüf değildir, derleme hızını doğrudan etkiler.
Katman önbelleği: talimat sırası derleme hızını belirler
Docker her talimatın sonucunu önbelleğe alır. Bir talimat ya da ona girdi olan dosyalar değişirse, o talimat ve ondan sonraki bütün katmanlar yeniden üretilir. Bu nedenle sık değişen şeyi Dockerfile'ın sonlarına, nadiren değişeni başlarına koyarsınız.
Yukarıdaki örnekte package dosyaları ayrıca kopyalanıp bağımlılık kurulumu önce çalıştırıldı. Yalnızca kaynak kod değiştiğinde bağımlılık kurulumu önbellekten gelir ve yeniden derleme çok hızlıdır. Her şeyi tek seferde kopyalayan Dockerfile'da ise tek satır kod değişikliği bile bağımlılıkları baştan indirtir.
Bir diğer yaygın kural: paket yöneticisi komutlarını birleştirmek. Docker belgelerine göre apt-get update ile apt-get install aynı RUN içinde olmalıdır; aksi halde eski bir önbellek katmanı eski paket listesiyle çalışır. Aynı RUN içinde paket listesi dizininin silinmesi de imaj boyutunu küçültür. Uzun komut zincirlerini ters eğik çizgiyle bölüp, çok satırlı paket listelerini alfabetik sıralamak gözden geçirmeyi kolaylaştırır.
Önbellek güncel taban imajı görmeyebilir. Güvenlik yamalı yeni imaj için derlemede çekme bayrağını (--pull) kullanabilir, tüm adımları sıfırdan çalıştırmak için önbelleği devre dışı bırakabilirsiniz (--no-cache).
Çok aşamalı derleme (multi-stage build)
Derleme araçları (derleyici, test kütüphaneleri, geliştirme bağımlılıkları) çalışma ortamında gerekmez ama tek aşamalı Dockerfile'da imajın içinde kalır. Docker'ın önerdiği çözüm çok aşamalı derlemedir: ilk aşamada derleme yapılır, son aşamaya yalnızca ürün kopyalanır.
FROM node:<sürüm> AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build
FROM node:<sürüm>-alpine WORKDIR /app COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules USER node CMD ["node", "dist/server.js"]
Son imaj yalnızca çalışma için gerekenleri içerir. Boyut küçülür, saldırı yüzeyi azalır. Derlenen dillerde (örneğin Go) bu fark çok büyüktür, çünkü son aşama neredeyse boş bir taban imajdan bile olabilir. Aşamalara ad vermek, bir aşamayı hata ayıklama için ayrı derlemeyi de mümkün kılar.
Taban imaj, güvenlik ve .dockerignore
Taban imaj seçimi, boyut ve güvenlik açısından en etkili karardır. Docker belgeleri güvenilir kaynaklardan gelen imajları (Docker Official Images gibi) ve gerekli olandan fazlasını içermeyen küçük tabanları önerir. Alpine gibi küçük imajlar boyutu düşürür; ancak eski kütüphane uyumsuzlukları çıkarabilir, bu yüzden uygulamanızla test edin.
Etiketler değiştirilebilir. Tekrarlanabilir derleme için taban imajı belirli bir sürüme, tam tekrarlanabilirlik için ise özet değerine (digest) sabitleyin. Sabitlenen sürümü düzenli güncelleyecek bir süreç (örneğin otomatik bağımlılık güncelleme aracı) kurmak gerekir.
Kök kullanıcı yerine yetkisiz kullanıcı ile çalıştırın. USER talimatıyla önceden oluşturulmuş ya da imajın sağladığı bir kullanıcı seçilir. Kimlik numarasının önemli olduğu durumlarda açıkça verin, çünkü imaj içindeki kullanıcı ve grup numaraları belirsiz atanır.
.dockerignore dosyası, derleme bağlamına girmemesi gereken dosyaları listeler. Örnek içerik:
node_modules .git .env *.log Dockerfile
Gizli bilgileri (.env, anahtarlar) bağlamdan çıkarmak hem imaj boyutunu hem sızıntı riskini azaltır. Gizli bilgiyi ENV ya da ARG ile imaja gömmeyin; bunlar katmanlarda iz bırakır.
CMD, ENTRYPOINT ve sinyaller
Dockerfile'ın son satırı, konteynerin ne yapacağını belirler. Docker belgeleri hizmetler için CMD'nin köşeli parantezli (exec) biçimini önerir: CMD ["çalıştırılabilir", "parametre"]. Bu biçim kabuk başlatmadığı için süreç doğrudan konteynerin ana süreci olur ve durdurma sinyalini alır. Kabuk biçiminde ise komut /bin/sh -c altında çalışır; uygulama sinyalleri düzgün almayabilir ve konteyner temiz kapanmaz.
ENTRYPOINT ana komutu, CMD ise varsayılan parametreleri tanımlamak için birlikte kullanılabilir. Bir yardımcı betik çalıştırıyorsanız betiğin sonunda exec kullanarak uygulamayı ana süreç yapın.
Her konteyner tek bir işe odaklanmalıdır: web uygulaması, veritabanı ve önbellek ayrı konteynerlerde çalışır. Bu, ölçeklemeyi ve güncellemeyi kolaylaştırır.
Sık yapılan hatalar ve kontrol listesi
- latest etiketini taban imaj olarak kullanmak: derleme zamanla farklı sonuç verir.
- Her şeyi tek seferde kopyalamak: önbellek her değişiklikte bozulur.
- Derleme bağımlılıklarını son imajda bırakmak: çok aşamalı derleme kullanın.
- Root olarak çalıştırmak: yetkisiz kullanıcıya geçin.
- .dockerignore yazmamak: derleme bağlamı gereksiz büyür.
- Gizli bilgiyi ENV, ARG veya COPY ile imaja gömmek.
- Gerekli olmayan paketleri "belki lazım olur" diye kurmak.
Yayından önce son kontrol: imaj temiz bir makinede derleniyor mu? Konteyner yetkisiz kullanıcıyla başlıyor mu? Durdurma komutuyla temiz kapanıyor mu? İmaj içinde gizli bilgi, geliştirme araçları ya da gereksiz dosya kaldı mı?
Mindset programlarında nerede çalışılır?
Temel Docker Eğitimi, uygulamasını konteynerleştirecek geliştiriciler ve sistem yöneticileri için bir başlangıç sunar; müfredatında Dockerfile ile özel imaj oluşturma başlığı ayrıca yer alır. Docker ve Container Teknolojileri eğitimi ise "Docker Image Oluşturma Sanatı" modülüyle imaj oluşturmaya daha derinlemesine odaklanır ve imaj güvenliği ile registry konularını da kapsar.
Kurumsal bir ekipte Dockerfile standartlarını ortaklaştırmak, ekipler arası farklı imaj boyutu ve güvenlik sorunlarını azaltır; ortak bir şablon tüm projelerde başlangıç noktası olabilir.
İlgili Mindset programı
Temel Docker Eğitimi
Sık sorulan sorular
Dockerfile'da COPY ile ADD arasındaki fark nedir?
Docker belgeleri çoğu durumda COPY kullanmayı önerir; çünkü yalnızca dosya kopyalar ve davranışı öngörülebilirdir. ADD ise uzak adresten dosya indirebilir ve sağlama değerini doğrulayabilir; bu özellik gerektiğinde tercih edilir. Aşamalar arası kopyalama için de COPY kullanılır.
CMD ile ENTRYPOINT'i ne zaman birlikte kullanmalıyım?
ENTRYPOINT konteynerin ana komutunu, CMD ise ona verilecek varsayılan parametreleri tanımlar. Konteyneri belirli bir araç gibi çalıştırmak ve kullanıcının docker run sırasında parametre değiştirebilmesini istiyorsanız birlikte kullanılır. Yalnızca bir hizmet başlatıyorsanız genellikle CMD yeterlidir.
Alpine imajı her zaman daha iyi bir seçim midir?
Küçük boyut avantajı sağlar ancak farklı bir C kütüphanesi kullandığı için bazı derlenmiş bağımlılıklarla uyumsuzluk çıkarabilir. Uygulamanızı hem alpine hem de standart tabanda deneyip, boyut, uyumluluk ve güvenlik güncellemelerini birlikte değerlendirmek daha sağlıklıdır.
Dockerfile'da gizli bilgi nasıl yönetilir?
Parolaları ve anahtarları ENV, ARG ya da COPY ile imaja yazmayın; imaj katmanlarında iz bırakırlar. Çalışma zamanında ortam değişkeni ya da secret mekanizmasıyla verin. Derleme sırasında gerekiyorsa derleme araçlarının gizli bilgi desteğini kullanın ve .dockerignore ile ilgili dosyaları bağlam dışında bırakın.
İmajım neden bu kadar büyük?
En sık nedenler: büyük bir taban imaj, derleme araçlarının son imajda kalması, gereksiz paketler ve .dockerignore eksikliği. Çok aşamalı derleme, küçük taban imaj, paket önbelleğinin aynı RUN içinde temizlenmesi ve gereksiz dosyaların bağlam dışında bırakılması boyutu belirgin biçimde düşürür.