Base image, Dockerfile'daki FROM satırında belirttiğiniz ve kendi imajınızın üzerine kurulduğu imajdır. Docker belgelerinin önerisi, güvenilir bir kaynaktan gelen ve gereksinimlerinizi karşılayan en küçük imajı seçmek, etiketlerin değişebileceğini bilerek sürümü bilinçli sabitlemek ve imajı düzenli olarak --pull ile yeniden build etmektir. Docker Official Images, Verified Publisher ve Docker Hardened Images bu güvenilir başlangıç noktalarının başında gelir.

Bu yazıda resmî imajların etiket varyantlarını (latest, slim, alpine, dağıtım kod adları), Alpine'ın musl farkını, scratch ile minimal imaj oluşturmayı, digest ile sabitlemenin artı ve eksilerini, Hardened Images'a geçişte nelerin değiştiğini ve Compose'ta taze base image çekmeyi anlatıyoruz. Multi-stage build temelleri için Dockerfile yazma rehberine, serinin geri kalanı için Docker öğrenme rehberi sayfasına bakabilirsiniz.

Base image nedir, kendiniz oluşturmanız gerekir mi?

Belgelere göre her Dockerfile bir base image ile başlar ve bu, FROM talimatının içeriğidir. Çoğu durumda kendi base image'ınızı oluşturmanız gerekmez; Docker Hub, base image olarak kullanılabilecek geniş bir imaj kütüphanesi sunar. İmajın içeriğini tamamen kontrol etmeniz gerekiyorsa iki yol vardır: özel FROM scratch başlangıcı ya da seçtiğiniz bir Linux dağıtımının kök dosya sistemini tar olarak paketleyip docker import ile içeri almak.

Belgelerdeki dağıtım örneği Debian'ın Debootstrap aracıyla bir Ubuntu kök dosya sistemi oluşturur ve bunu imaja çevirir; noble kod adı Ubuntu 24.04'ü gösterir. Kendi dağıtım imajınızı tutmak, güncellemelerini de sizin yapmanız anlamına gelir; bu yüzden çoğu sunucu senaryosunda resmî bir imajdan başlamak daha az bakım yükü getirir.

bash
sudo debootstrap noble noble > /dev/null
sudo tar -C noble -c . | docker import - noble
docker run noble cat /etc/lsb-release

Güvenilir içerik programları

Güvenilir içerik programları: Docker Official Images, Docker Hardened Images, Verified Publisher, Docker-Sponsored Open Source

Docker Hub'ın güvenilir içerik başlığı altında dört grup bulunur ve her biri Docker Hub'da kendine özgü bir rozetle işaretlenir. Base image seçerken bu rozetlere bakmak, en iyi uygulamalar sayfasının ilk önerisidir.

ProgramKim yayımlarÖne çıkan özellik
Docker Official ImagesDocker tarafından derlenen depolarAçık belgeler, en iyi uygulamalar, düzenli güncelleme
Docker Hardened ImagesDockerMinimal, üretime hazır, imzalı SBOM ve provenance metaverisi
Verified PublisherDocker'ın doğruladığı ticari yayıncılarİçeriğin özgünlüğü Docker tarafından doğrulanır
Docker-Sponsored Open SourceDocker'ın desteklediği açık kaynak projelerAktif ve güvenilir olarak doğrulanmış projeler

Docker, projelerinizde Docker Official Images kullanmanızı önerir. Bu imajlar Ubuntu ve Alpine gibi işletim sistemlerini, Python ve Node gibi dil çalışma zamanlarını ve memcached, MySQL gibi temel araçları kapsar. Belgelere göre bu imajlar genellikle CVE içeren çok az paket barındırır ya da hiç barındırmaz ve Dockerfile en iyi uygulamalarına örnek olacak şekilde hazırlanır. Kullanımlarının Docker Hizmet Koşullarına tabi olduğunu da not edin.

Etiketleri okumak: latest, slim, alpine ve kod adları

Her resmî imajın depo açıklamasında "Supported tags and respective Dockerfile links" bölümü bulunur; bu bölüm güncel etiketleri ve her etiketi üreten Dockerfile'ın bağlantısını listeler. Aynı satırda yazılan etiketler aynı imajı gösterir: belgelerdeki Ubuntu örneğinde 24.04, noble-20240225, noble ve devel aynı imajdır. Hangi etiketin ne içerdiğini anlamanın en güvenilir yolu imajın "How to use this image" ve "Image Variants" bölümlerini okumaktır.

  • latest: Resmî imajlarda çoğunlukla kullanım kolaylığına göre ayarlanır ve geliştirici ile build araçları gibi geniş bir yazılım seti içerebilir. Belgeler, hangi etiketi kullanacağınızı bilmiyorsanız buradan başlayabileceğinizi, yazılımı tanıdıkça başka varyantların daha uygun olabileceğini söyler.
  • slim: Node.js, Python ve Ruby gibi dil imajlarında bulunur; daha az paket içeren, üretime hazır hafif bir taban sunar. Tipik kullanımı çok aşamalı build'in son aşamasıdır: uygulama latest varyantında build edilir, slim tabanlı son aşamaya kopyalanır.
  • alpine: Debian ya da Ubuntu yerine Alpine Linux üzerine kuruludur ve genellikle slim varyantlarından da küçüktür. En iyi uygulamalar sayfası Alpine imajının 6 MB altında olduğunu ve yine de tam bir Linux dağıtımı olduğunu belirtir.
  • Kod adları: bookworm, bullseye, trixie gibi Toy Story karakterleri Debian'ı, jammy ve noble gibi sıfat ve hayvan adları Ubuntu sürümlerini gösterir. postgres:bookworm ve postgres:trixie gibi varyantlar, aynı yazılımın farklı dağıtım sürümleri üzerine kurulduğunu anlatır.
dockerfile
FROM node:latest AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . ./
FROM node:slim
WORKDIR /app
COPY --from=build /app /app
CMD ["node", "app.js"]

Alpine ve musl: neye dikkat etmeli?

Alpine ve musl: neye dikkat etmeli? Programı musl libc'ye karşı derlemek., glibc kütüphanelerini programa statik olarak bağlamak., C bağımlılıklarından tamamen kaçınmak, örneğin...

Alpine Linux, glibc yerine musl libc kullanır. Belgeler ayrıca boyutu küçük tutmak için Alpine tabanlı imajlarda Git ya da Bash gibi araçların varsayılan olarak bulunmamasının yaygın olduğunu belirtir. Programınızın libc'ye ne kadar bağımlı olduğuna göre eksik kütüphane veya araç sorunlarıyla karşılaşabilirsiniz. Belgelerin önerdiği seçenekler şunlardır:

  • Programı musl libc'ye karşı derlemek.
  • glibc kütüphanelerini programa statik olarak bağlamak.
  • C bağımlılıklarından tamamen kaçınmak, örneğin Go programlarını CGO olmadan build etmek.
  • İhtiyaç duyduğunuz yazılımı Dockerfile'da kendiniz eklemek.

Sunucu tarafında bu, özellikle yerel uzantıları olan Python veya Node.js paketlerinde ve hazır derlenmiş ikili dosya indiren kurulum betiklerinde önem taşır. Alpine imajına geçtikten sonra uygulamanız açılmıyorsa ilk bakılacak yerlerden biri libc farkıdır. Bu durumda slim varyantı daha az sürprizle benzer bir küçülme sağlayabilir.

scratch ile minimal imaj

Ayrılmış scratch imajı en küçük başlangıç noktasıdır. Belgelere göre FROM scratch, build sürecine bir sonraki komutun imajdaki ilk dosya sistemi katmanı olmasını istediğinizi söyler. scratch Docker Hub'da görünse de onu çekemez, çalıştıramaz ve hiçbir imaja scratch adını veremezsiniz; yalnızca Dockerfile içinde başvurabilirsiniz.

dockerfile
# syntax=docker/dockerfile:1
FROM scratch
ADD hello /
CMD ["/hello"]

Bu örnek, build context'in kökünde hello adlı çalıştırılabilir bir ikili dosya olduğunu varsayar ve ancak bu ikilinin hiçbir çalışma zamanı bağımlılığı yoksa çalışır. Belgeler programların genellikle bir dil çalışma zamanına, dinamik bağlı C kütüphanelerine ve CA sertifikalarına ihtiyaç duyduğunu hatırlatır. Bu yüzden scratch küçük ve basit programlar dışında zor bir seçimdir; öte yandan imaja yalnızca gerekeni koymak boyutu ve saldırı yüzeyini azaltır. Statik derlenmiş bir Go servisi için uygun, Python uygulaması için ise pratikte uygun değildir.

Docker Hardened Images'a geçiş

Docker Hardened Images (DHI), Docker'ın bakımını yaptığı minimal ve üretime hazır base ve uygulama imajlarıdır. Belgelere göre Docker bu imajlarda CVE sayısını sıfıra yakın tutar ve imajlar SBOM ile provenance attestation gibi imzalı güvenlik metaverisi içerir. Geçiş listesi, alışık olduğunuz resmî imajlara göre neyin değiştiğini açıkça sıralar:

  • Çalışma zamanı imajları varsayılan olarak root olmayan kullanıcıyla (UID 65532) çalışır; uygulamanın okuyup yazacağı dosya ve dizinlerin bu kullanıcıya açık olması gerekir.
  • Çalışma zamanı imajlarında paket yöneticisi ve kabuk yoktur. Paket kurulumu ve kabuk komutları dev ya da sdk etiketli build aşamalarına taşınır, gerekli çıktılar son aşamaya kopyalanır.
  • CA sertifikaları varsayılan olarak bulunduğu için bunları kuran adımlar kaldırılabilir.
  • Yetkisiz kullanıcı Kubernetes'te veya 20.10'dan eski Docker Engine sürümlerinde 1024 altındaki portlara bağlanamadığından uygulamanın container içinde 1025 veya üzerindeki bir portu dinlemesi önerilir.
  • Entry point resmî imajdan farklı olabilir; docker inspect veya imaj belgeleriyle kontrol edip ENTRYPOINT ya da CMD talimatlarınızı güncellemeniz gerekebilir.

Bu maddelerin bir kısmı Dockerfile alışkanlıklarını doğrudan etkiler: kabuk olmadığı için başlangıç komutunun exec form ile yazılması gerekir. Bu konu CMD ve ENTRYPOINT yazısında, yetkisiz kullanıcıyla çalışmanın sunucu tarafı ise rootless mod yazısında ele alınıyor.

Etiketler değişebilir: sürüm ve digest sabitleme

İmaj etiketleri değiştirilebilir; yayıncı bir etiketi yeni bir imaja yönlendirebilir. Belgelerdeki örnekte FROM alpine:3.21, 3.21 serisinin en son yama sürümüne çözülür: bugün 3.21.1 olan imaj, üç ay sonra yeniden build ettiğinizde 3.21.4 olabilir. Bu yayın düzeni en iyi uygulamadır ve çoğu yayıncı böyle çalışır ama zorunlu değildir. Avantajı, yeniden build ettiğinizde güvenlik düzeltmelerini kendiliğinden almanızdır; dezavantajı her build'de aynı imajı alacağınızın garanti olmaması, kırıcı değişiklik ihtimali ve tam olarak hangi sürümü kullandığınıza dair bir denetim kaydınızın olmamasıdır.

Tedarik zincirinin bütünlüğünü tam olarak korumak için imajı bir digest'e sabitleyebilirsiniz. Digest ile sabitlenen bir FROM, yayıncı etiketi başka bir imaja taşısa bile her zaman aynı imajı kullanır:

dockerfile
# syntax=docker/dockerfile:1
FROM alpine:3.21@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c

Belgeler bunun bedelini de açıkça söyler: her güncellemede digest'i elle bulup yazmak zahmetlidir ve otomatik güvenlik düzeltmelerinden vazgeçmiş olursunuz. Önerilen orta yol, sabitlemeyi bir otomasyona bağlamaktır. GitHub Dependabot package-ecosystem: "docker" ayarıyla base image etiketlerini ve digest'lerini güncelleyen pull request'leri zamanlanmış olarak açar; belgelere göre bu, sürümü kendiliğinden değiştiren bir etikete güvenmekten daha iyidir, çünkü kontrol sizdedir ve değişikliğin ne zaman ve nasıl olduğu kayıt altındadır. Docker Scout'un varsayılan "No outdated base images" politikası da kullandığınız base image sürümünün gerçekten en yenisi olup olmadığını ve sabitlenmiş digest'lerin doğru sürüme karşılık gelip gelmediğini kontrol eder; docker scout recommendations komutu mevcut güncellemeleri CLI'dan incelemenizi sağlar.

Deneysel durumdaki build politikaları bir adım daha ileri gidebilir: belgelerde örnek olarak Docker imajlarının yalnızca etiketle değil digest referanslarıyla kullanılmasını zorunlu kılan kurallar sayılır. Sürüm numarasını bir ARG ile dosyanın başına almak ise güncellemeyi tek satıra indirir; kapsam kuralları ARG ve ENV yazısında.

Düzenli yeniden build: --pull ve --no-cache

Düzenli yeniden build: --pull ve --no-cache: --pull, --no-cache, İkisi birlikte

Docker imajları değişmezdir; bir imajı build etmek o anın, kullandığınız base image ve kütüphaneler dahil, bir anlık görüntüsünü almaktır. Belgeler imajları güncel ve güvenli tutmak için onları güncel bağımlılıklarla düzenli olarak yeniden build etmenizi önerir. Burada iki bayrak farklı işler yapar:

BayrakNe yaparNe yapmaz
--pullYerelde önbelleğe alınmış bir sürüm olsa bile base image'ın daha yeni sürümünü kontrol edip indirirSonraki adımların önbelleğini kendiliğinden temizlemez
--no-cacheBuild önbelleğini devre dışı bırakır ve tüm katmanları sıfırdan build eder; apt-get veya npm gibi paket yöneticilerinden güncel sürümleri alırTaze base image çekmez
İkisi birlikteTaze base image ile bütün adımları yeniden çalıştırır
bash
docker build --pull -t my-image:my-tag .
docker build --pull --no-cache -t my-image:my-tag .

Compose ile build ediyorsanız aynı davranışlar build bölümündeki alanlarla ayarlanır: pull: true, FROM talimatında başvurulan imajları yerel imaj deposunda bulunsalar bile çekmeye zorlar. Aşağıdaki dosya Docker CLI 29.8.1, Docker Compose v5.5.1 ile docker compose config --quiet çıkış kodu 0 verdi:

yaml
services:
  app:
    build:
      context: .
      pull: true
      no_cache: true
  cache:
    image: redis:7-alpine

Base image güncellemesini Dockerfile'ı değiştirmeden denemek için named context'ler de kullanılabilir. Belgelerdeki örnekte FROM alpine:3.21 içeren bir Dockerfile, docker buildx build --build-context alpine:3.21=docker-image://alpine:edge . komutuyla farklı bir imaja karşı build edilir. Bu yöntem build context yazısında ayrıntılı anlatılıyor.

Docker Hub ve DOCKER_CONTENT_TRUST notu

Base image çekmek Docker Hub kullanım limitlerine tabidir; sık yeniden build eden CI hatlarında bu limitler Docker Hub pull limiti yazısında anlatılıyor. Resmî imajları çekerken başarısız oluyorsanız, güvenilir içerik sayfası DOCKER_CONTENT_TRUST ortam değişkeninin 1 olarak ayarlı olup olmadığını kontrol etmenizi söyler: Docker Content Trust kullanımdan kaldırılmaktadır ve servis çekmeler için artık güvenilir değildir, çözüm değişkeni kaldırmaktır. Engine 29.0.0 sürüm notları da Docker Content Trust'ın Docker CLI'dan çıkarıldığını kaydeder.

Seçim için pratik bir yol

Belgelerin önerilerini bir araya getirince sunucuda çalışan bir uygulama için şu sıra ortaya çıkar. Önce rozetli bir kaynaktan, mümkünse Docker Official Images ya da Docker Hardened Images içinden, uygulamanızın dilini sağlayan imajı bulun. Build ve test için araçları bol bir varyant, üretim için ise daha ince bir varyant kullanın; belgeler bu iki tür base image ayrımını, son aşamada derleyici, build sistemi ve hata ayıklama araçlarına gerek olmadığı için saldırı yüzeyini belirgin şekilde azaltan bir yöntem olarak anlatır. Alpine düşünüyorsanız libc bağımlılıklarınızı kontrol edin. Sürümü en azından ana ve ara sürüm düzeyinde sabitleyin, digest sabitlemesini bir otomasyonla yönetin ve imajı düzenli aralıklarla --pull ile yeniden build edin.

Sık yapılan hatalar

  • Üretim imajında sürümsüz latest kullanmak: aynı Dockerfile farklı zamanlarda farklı imajlar üretir ve denetim kaydı kalmaz.
  • Digest sabitleyip hiç güncellememek: otomatik güvenlik düzeltmelerinden vazgeçmiş olursunuz.
  • --no-cache kullanınca base image'ın da tazelendiğini sanmak: bunun için --pull gerekir.
  • Alpine'a geçerken musl farkını hesaba katmamak.
  • Bağımlılıkları olan bir programı scratch üzerine koymak: çalışma zamanı, C kütüphaneleri ya da CA sertifikaları eksik kalır.
  • Hardened Images'a geçerken root olarak çalışmaya ve kabuk bulunmasına dayanan adımları son aşamada bırakmak.
  • Rozeti olmayan, kaynağı belirsiz bir imajı base image yapmak.

Sık Sorulan Sorular

Alpine mi slim mi seçmeliyim?

Alpine genellikle daha küçüktür ama musl libc kullanır ve Git, Bash gibi araçları varsayılan olarak içermeyebilir. Programınız glibc'ye bağımlıysa slim varyantı daha az uyumluluk sorunu çıkarır.

Digest ile sabitlemek zorunlu mu?

Zorunlu değildir. Digest her build'de aynı imajı garanti eder ama güncellemeyi size bırakır. Belgeler bu yüzden digest sabitlemeyi Dependabot gibi güncellemeleri pull request olarak açan bir araçla birlikte önerir.

scratch imajını docker pull ile indirebilir miyim?

Hayır. scratch ayrılmış bir addır; çekilemez, çalıştırılamaz ve bir imaja etiket olarak verilemez. Yalnızca Dockerfile'da FROM scratch olarak kullanılır.

Base image'ı ne sıklıkla yenilemeliyim?

Belgeler belirli bir süre vermez, imajları güncel bağımlılıklarla düzenli olarak yeniden build etmeyi önerir. Bunu CI hattınızda zamanlanmış bir build ile yapmak ve --pull kullanmak pratik bir yoldur.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: Docker öğrenme rehberi · ARG ve ENV farkı · CMD ve ENTRYPOINT farkı · Docker Hub pull limiti · Multi-platform build · Dockerfile yazma rehberi