Build context, docker build komutuna verdiğiniz son argümanın gösterdiği ve build sırasında builder'ın erişebildiği dosyaların tamamıdır. docker build . yazdığınızda nokta, içinde bulunduğunuz dizini context yapar; Dockerfile içindeki COPY ve ADD yalnızca bu kümedeki dosyalara ulaşabilir. .dockerignore dosyası ise bu kümeden neyin çıkarılacağını belirler ve dosyalar builder'a gönderilmeden önce uygulanır.

Bu yazıda yerel dizin, tarball, Git deposu ve boş context türlerini, .dockerignore desenlerinin tam olarak nasıl eşleştiğini, birden fazla kaynağı tek build'e bağlayan named context özelliğini ve aynı ayarların Compose dosyasında nasıl yazıldığını resmî belgelere dayanarak anlatıyoruz. Temel Dockerfile yazımı için Dockerfile yazma rehberine, serinin geri kalanı için Docker öğrenme rehberi sayfasına bakabilirsiniz.

Build context komutun neresinde durur?

Docker belgeleri komutun genel biçimini docker build [OPTIONS] PATH | URL | - olarak gösterir. Sondaki konumsal argüman context'tir ve üç tür değer alabilir: yerel bir dizinin göreli ya da mutlak yolu; bir Git deposunun, tarball'un veya düz metin dosyasının uzak adresi; ya da standart girdiden borulanan bir tarball veya metin dosyası (-).

Bu girdiler iki gruba ayrılır. Yerel dizin, Git deposu ve tar arşivi bir dosya sistemi context'i oluşturur: builder bu dosyalara erişir ve işlem özyinelemelidir, yani yerel dizin ya da tarball verdiğinizde tüm alt dizinler, Git deposu verdiğinizde ise depo ve bütün submodule'leri dahil edilir. Düz metin dosyası verdiğinizde ise builder bu dosyayı doğrudan Dockerfile olarak yorumlar ve ortada hiçbir dosya sistemi context'i olmaz.

Bu ayrımın pratik sonucu şudur: Dockerfile ile context aynı şey değildir. Dockerfile build talimatlarını içerir, context ise o talimatların okuyabileceği dosyaları. Dockerfile'ın varsayılan adı uzantısız Dockerfile'dır ve belgeler projenin ana Dockerfile'ı için bu adın kullanılmasını önerir; farklı amaçlar için yaygın gelenek <bir-sey>.Dockerfile adlandırmasıdır ve bu dosyayı --file (kısaca -f) bayrağıyla seçersiniz.

Yerel dizin ve tarball context'i

Sunucuda en sık kullanılan biçim yerel dizindir. Aşağıdaki komut mevcut dizini context olarak kullanır; builder ihtiyaç duyduğu dosyaları build sırasında context'ten yükler. Belgelerdeki örnekte build çıktısında [internal] load build context adımı ve aktarılan context boyutu görünür; büyük bir context bu adımı yavaşlatır.

bash
docker build -t uygulama:latest .

Dockerfile'ın context içinde bulunmasını beklemezseniz -f- sözdizimiyle Dockerfile'ı standart girdiden verip dosyaları yine yerel dizinden alabilirsiniz. Tire işareti, Docker'a Dockerfile'ı stdin'den okumasını söyler. Belgelerdeki örneğe dayanan şu komut mevcut dizini context yapar ve Dockerfile'ı bir here-document ile iletir:

bash
docker build -t myimage:latest -f- . <<EOF
FROM busybox
COPY somefile.txt ./
RUN cat /somefile.txt
EOF

Context'i bir tar arşivi olarak da borulayabilirsiniz. Bu durumda build arşivin içeriğini dosya sistemi context'i olarak kullanır ve Dockerfile'ı arşivin içinden çözer. --file bayrağına verilen yol, arşivin köküne göre yorumlanır:

bash
tar czf foo.tar.gz *
docker build - < foo.tar.gz
docker build --file test.Dockerfile - < foo.tar.gz

Git deposunu context olarak kullanmak

Git deposunu context olarak kullanmak: myrepo.git, myrepo.git#mytag, myrepo.git#mybranch, myrepo.git#pull/42/head

Bir Git deposunun adresini verdiğinizde builder depoyu kendisi klonlar. Klon sığdır: geçmişin tamamı değil yalnızca HEAD commit'i indirilir ve depo içindeki submodule'ler de özyinelemeli olarak alınır. Ek bir belirteç yoksa varsayılan dalın en son commit'i kullanılır.

Belirli bir dalı, etiketi ya da alt dizini seçmek için adresin sonuna #ref:dir biçiminde bir URL parçası eklersiniz. ref dal, etiket veya commit hash'i; dir ise depo içindeki alt dizindir. Commit hash'i kullanacaksanız tam 40 karakterlik SHA-1 değerini yazmalısınız; yedi karaktere kısaltılmış bir hash bu sözdiziminde desteklenmez.

SonekKullanılan commitContext dizini
myrepo.gitvarsayılan dalın ucu/
myrepo.git#mytagrefs/tags/mytag/
myrepo.git#mybranchrefs/heads/mybranch/
myrepo.git#pull/42/headrefs/pull/42/head/
myrepo.git#:myfoldervarsayılan dalın ucu/myfolder
myrepo.git#mybranch:myfolderrefs/heads/mybranch/myfolder

Belgeler, URL parçalarına göre daha yapılı olan URL sorgularını önerir. branch, tag, ref ve subdir parametreleri aynı seçimleri yapar; ek olarak checksum (takma adı commit) parametresiyle referansın beklediğiniz commit'e çözüldüğünü doğrulayabilirsiniz. Eşleşme yoksa build hata verir. Sorgu biçiminde kısa hash kabul edilir; ref ile verilen commit için ise yine tam hash gerekir. Builder'ınız ya da Dockerfile frontend'iniz sorguları desteklemiyorsa BUILDX_SEND_GIT_QUERY_AS_INPUT=1 ayarı sorguyu Buildx tarafında çözer; bu ayar context'in provenance kaydındaki gösterimini değiştirir.

bash
docker buildx build 'https://github.com/moby/buildkit.git?tag=v0.21.1&checksum=66735c67'

BuildKit varsayılan olarak Git context'lerinde .git dizinini saklamaz. Build içinde commit bilgisini okumak istiyorsanız BUILDKIT_CONTEXT_KEEP_GIT_DIR build argümanını ayarlarsınız. Özel depolarda builder'ın kimlik bilgisine ihtiyacı vardır: SSH ya da Git adresinde Buildx SSH kimliğini otomatik algılar ve varsayılan olarak $SSH_AUTH_SOCK kullanır; token tabanlı kimlik için --secret id=GIT_AUTH_TOKEN verilir. Belgeler bu noktada açıkça uyarır: sırlar için --build-arg kullanmayın. Ayrıntılar build secrets yazısında.

bash
docker build --build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 https://github.com/user/myrepo.git#main
docker buildx build --ssh default git@github.com:user/private.git

Uzak tarball ve uzak builder'da dikkat edilecek nokta

Uzak tarball ve uzak builder'da dikkat edilecek nokta

Uzak bir tarball adresi verdiğinizde adresin kendisi builder'a gönderilir ve indirme BuildKit daemon'unun çalıştığı makinede yapılır. Belgeler, uzak bir Docker context'i ya da uzak bir builder kullanıyorsanız bunun komutu yazdığınız makine olmayabileceğini hatırlatır. Yani yerel ağınızdan erişilebilen ama build sunucusundan erişilemeyen bir adres bu yöntemle çalışmaz. Arşiv standart Unix tar biçiminde olmalı; sıkıştırma için xz, bzip2, gzip ya da sıkıştırmasız identity kabul edilir. Uzak engine yönetimini docker context yazısında ayrıca ele alıyoruz.

Boş context: yalnızca Dockerfile ile build

Dockerfile'ınız hiçbir yerel dosyaya ihtiyaç duymuyorsa context göndermeden build alabilirsiniz. Metin dosyasını stdin üzerinden ya da uzak bir metin dosyasının adresiyle verirsiniz; builder bunu Dockerfile olarak kullanır. Bu modda COPY yerel dosyalara başvuramaz: belgelerdeki örnekte COPY main.c . satırı, dosya dizinde dursa bile "/main.c": not found hatasıyla sonuçlanır, çünkü builder'a hiçbir dosya gönderilmemiştir.

bash
docker build - < Dockerfile

.dockerignore dosyası nerede aranır?

Build istemcisi context'in kök dizininde .dockerignore adlı dosyayı arar. Dosya varsa, desenlerle eşleşen dosya ve dizinler context builder'a gönderilmeden önce çıkarılır. Bu hem aktarılan veri miktarını azaltır, hem de gereksiz dosyalardaki değişikliklerin önbelleği bozma ihtimalini düşürür; belgeler bunun özellikle uzak builder kullanırken build hızına etki ettiğini belirtir.

Birden fazla Dockerfile kullanıyorsanız her biri için ayrı bir ignore dosyası tanımlayabilirsiniz. Dosyayı Dockerfile ile aynı dizine koyar ve adına Dockerfile'ın adını önek olarak verirsiniz: build.Dockerfile için build.Dockerfile.dockerignore gibi. İkisi birden varsa Dockerfile'a özel olan, context kökündeki .dockerignore dosyasının önüne geçer.

.dockerignore desenleri nasıl eşleşir?

.dockerignore desenleri nasıl eşleşir? */temp*, */*/temp*, temp?, **/*.go

Dosya, satır satır yazılmış ve Unix kabuklarındaki glob'lara benzeyen desenlerden oluşur. Desenlerin başındaki ve sonundaki eğik çizgiler yok sayılır; bu yüzden /foo/bar/, /foo/bar, foo/bar/ ve foo/bar aynı şeyi, kökteki foo altındaki bar öğesini dışlar. İlk sütunda # ile başlayan satırlar yorumdur. Eşleştirme Go'nun filepath.Match kurallarıyla yapılır; öncesinde filepath.Clean ile boşluklar kırpılır, . ve .. temizlenir ve bu işlemden sonra boş kalan satırlar atlanır. Tarihsel nedenlerle tek başına . deseni yok sayılır.

DesenDavranış
*/temp*Kökün hemen altındaki herhangi bir dizinde adı temp ile başlayan dosya ve dizinleri dışlar, örneğin /somedir/temporary.txt
*/*/temp*Kökten iki seviye aşağıdaki dizinlerde adı temp ile başlayanları dışlar
temp?Kök dizinde temp ve ardından tek karakter gelen adları dışlar, örneğin /tempa
**/*.goContext içinde herhangi bir derinlikte .go ile biten dosyaları dışlar

Son satırdaki **, Go kurallarının ötesinde Docker'ın eklediği özel bir jokerdir ve sıfır dahil istediğiniz sayıda dizinle eşleşir. Bu ayrım önemlidir: *.md gibi bir desen yalnızca context kökündeki Markdown dosyalarını dışlar, alt dizinlerdekiler context'te kalır. Her yerde eşleşmesini istiyorsanız **/*.md yazmanız gerekir.

Ünlem işaretiyle başlayan satırlar istisna tanımlar. Kural basittir: bir dosyayla eşleşen son satır, dosyanın dahil mi hariç mi olacağına karar verir. Aşağıdaki ilk dosyada README dosyaları geri alınır ama en sondaki satır README-secret.md dosyasını yeniden dışlar. Satırların yerini değiştirdiğinizde ise !README*.md en son eşleşen kural olur ve gizli README de context'e girer.

bash
*.md
!README*.md
README-secret.md

Dockerfile ve .dockerignore dosyalarını da dışlayabilirsiniz. Bu dosyalar build'i çalıştırmak için yine builder'a gönderilir, ama ADD, COPY ya da bind mount ile imaja kopyalanamaz. Sürüm notlarında da bu dosyayla ilgili bir kayıt var: Engine 29.3.1, .dockerignore içinde geçersiz bir desen bulunduğunda docker build sırasında daemon'un çökmesine yol açan bir hatayı düzeltir.

Küçük bir Node.js projesi için başlangıç noktası olarak şöyle bir dosya düşünebilirsiniz. Hangi satırların gerekli olduğu projenize bağlıdır; amaç imaja girmesi gerekmeyen, sık değişen ya da büyük dosyaları context dışında bırakmaktır.

bash
# bağımlılıklar imaj içinde yeniden kurulur
node_modules
# sürüm kontrolü ve geçici dosyalar
.git
tmp*
**/*.log
# belgeler, README hariç
*.md
!README.md

Named context ile birden fazla kaynak

Varsayılan context'e ek olarak --build-context ad=kaynak bayrağıyla adlandırılmış context'ler verebilirsiniz. Böylece farklı kaynaklardaki dosyalar mantıksal olarak ayrı kalır. Dockerfile bu context'lere çok aşamalı build'deki bir aşamaya başvurur gibi başvurur: COPY --from=config ... ya da RUN --mount=from=docs,target=....

bash
docker build --build-context docs=./docs .
docker build --build-context scripts=https://github.com/user/deployment-scripts.git .
dockerfile
# syntax=docker/dockerfile:1
FROM nginx:alpine
# "config" context'inden ortama özel ayar
COPY --from=config nginx.conf /etc/nginx/nginx.conf

Belgelerin gösterdiği üçüncü kullanım bir imaj referansını Dockerfile'ı değiştirmeden geçersiz kılmaktır. Context adı Dockerfile'daki imaj adıyla aynı olduğunda, docker-image:// önekiyle verdiğiniz imaj o referansın yerine geçer. Örneğin FROM alpine:3.21 yazan bir Dockerfile'ı --build-context alpine:3.21=docker-image://alpine:edge ile farklı bir sürüme karşı deneyebilirsiniz. Bake dosyalarında aynı şey contexts alanıyla yazılır ve target: önekiyle başka bir Bake hedefinin çıktısı temel imaj olarak bağlanabilir; bu konu Buildx Bake yazısının kapsamında.

Compose dosyasında context ayarları

Compose'ta build anahtarı kısa biçimde yalnızca context yolunu alır; bu yol Compose dosyasının klasörüne göredir, bir dizin olmalı ve içinde Dockerfile bulunmalıdır. Uzun biçimde context göreli yolsa proje dizinine göre yorumlanır ve belirtilmezse varsayılan değer proje dizinidir (.). Mutlak yol kullandığınızda Compose dosyanın taşınabilirliğini bozduğu için uyarır. dockerfile alanındaki göreli yol context'e göre çözülür; dockerfile_inline ile birlikte kullanılamaz, ikisi birden yazılırsa dosya reddedilir.

additional_contexts, CLI'daki named context'lerin karşılığıdır ve liste ya da eşleme olarak yazılabilir. Compose en az dizin yollarını ve Git adreslerini destekler; başka türler docker-image:// gibi bir önekle yazılmalıdır. service: önekiyle başka bir servisin build ettiği imaja da başvurabilirsiniz. Aşağıdaki dosya Docker CLI 29.8.1, Docker Compose v5.5.1 ile docker compose config --quiet komutundan çıkış kodu 0 ile geçti:

yaml
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
      additional_contexts:
        docs: ./docs
        alpine: docker-image://alpine:3.21
dockerfile
# syntax=docker/dockerfile:1
FROM alpine
WORKDIR /app
COPY . /app/src
RUN --mount=from=docs,target=/app/docs ls /app/docs

Compose dosyasının geri kalanı, servisler ve volume'lar gibi konular için Docker Compose rehberine bakabilirsiniz.

Sık yapılan hatalar

  • Komutu proje kökü yerine başka bir dizinden çalıştırmak: context yanlış dizini gösterdiği için COPY dosyaları bulamaz.
  • *.log gibi bir desenin alt dizinleri de kapsadığını varsaymak: kök dışındaki eşleşmeler için **/ gerekir.
  • İstisnayı (!) genel kuralın önüne yazmak: son eşleşen satır kazandığı için istisna etkisiz kalır.
  • Git context'inde kısa commit hash'ini URL parçası olarak vermek: tam 40 karakter gerekir.
  • Özel depo token'ını --build-arg ile geçirmek: belgeler bunun yerine --secret kullanılmasını söyler.
  • Uzak builder kullanırken uzak tarball'un yerel makineden indirileceğini sanmak: indirme BuildKit'in çalıştığı makinede olur.

Sık Sorulan Sorular

Dockerfile'ın context dizininde olması şart mı?

Hayır. -f ile başka bir yoldaki Dockerfile'ı seçebilir ya da -f- ile Dockerfile'ı stdin'den verip dosyaları yine yerel dizinden alabilirsiniz. Tarball context'inde ise --file yolu arşivin köküne göre yorumlanır.

.dockerignore ile dışladığım dosya build'i hızlandırır mı?

Dışlanan dosyalar builder'a gönderilmez, bu yüzden aktarılan veri azalır. Ayrıca bu dosyalar COPY . . gibi geniş kopyalara girmediği için değiştiklerinde önbelleği geçersiz kılmazlar.

Her Dockerfile için ayrı ignore dosyası tutabilir miyim?

Evet. Dockerfile ile aynı dizinde <ad>.Dockerfile.dockerignore biçiminde bir dosya oluşturursunuz; varsa kökteki .dockerignore dosyasının önüne geçer.

Named context ile çok aşamalı build arasındaki fark nedir?

Dockerfile içinde ikisine de aynı biçimde başvurulur, ama named context dışarıdan verilir: bir dizin, Git deposu ya da docker-image:// ile bir imaj olabilir. Aşama ise Dockerfile içinde tanımlanır.

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 · COPY ve ADD farkı · Docker build secrets · Build cache backend'leri · Buildx Bake · Dockerfile yazma rehberi