Docker Compose Watch, servis tanımındaki develop.watch kurallarına göre yerel dosyalarınızı izler ve bir dosya değiştiğinde ilgili container'ı kendiliğinden günceller: değişen dosyayı container içine kopyalar (sync), imajı yeniden derleyip container'ı yeniden oluşturur (rebuild) ya da dosyayı kopyalayıp servisi yeniden başlatır (sync+restart). Özelliği docker compose up --watch veya ayrı docker compose watch komutuyla açarsınız. Böylece her kod değişikliğinden sonra elle docker compose up --build çalıştırma alışkanlığı ortadan kalkar.
Bu yazı yalnızca watch modunu anlatır: kurallar nasıl yazılır, hangi eylem hangi durumda seçilir, bind mount ile farkı nedir ve en sık hangi hatalar yapılır. Tek servisli bir Compose dosyasını ilk kez yazıyorsanız önce Docker Compose başlangıç rehberine, çok servisli yapı ve override dosyaları için Docker Compose rehberine bakın. Tüm seri için Docker öğrenme rehberi sayfası başlangıç noktasıdır.
Watch modu ne işe yarar, neyi izlemez?

Watch, kaynak kodu yerelde duran ve build özniteliğiyle derlenen servisler için tasarlanmıştır. Belgeler bunu açıkça söyler: yalnızca image ile hazır bir imaj çeken servislerde dosya değişikliği izlenmez. Yani postgres:18 veya redis gibi hazır imajlarla çalışan bir veritabanı servisine watch kuralı yazmanın bir anlamı yoktur; watch'ı kendi yazdığınız uygulama servislerinde kullanırsınız.
Projedeki her servis için watch açmak zorunda da değilsiniz. Örneğin bir projede yalnızca JavaScript ön yüzü anlık güncellemeye uygun olabilir, arka uç ise ayrı bir derleme düzenine sahip olabilir. Kurallar servis bazında tanımlandığı için hangi servisin izleneceğine siz karar verirsiniz.
Watch'ın dosya yollarıyla ilgili kuralları şunlardır:
- Yollar proje dizinine göre yazılır. Tek istisna
ignoredesenleridir; onlar kuralın kendipathdeğerine göre yorumlanır. - Dizinler alt klasörleriyle birlikte (özyinelemeli) izlenir.
pathdeğerinde glob deseni desteklenmez;./src/*.jsgibi bir yol yazamazsınız. Dosya seçmek içinincludeveignorekullanılır.- Build context içindeki
.dockerignorekuralları watch için de geçerlidir;ignoreile eklediğiniz desenler bunların üstüne eklenir. - Vim, Emacs, JetBrains gibi yaygın editörlerin geçici ve yedek dosyaları ile
.gitdizinleri otomatik olarak yok sayılır.
.dockerignore dosyasının nasıl yazıldığını build context ve .dockerignore yazısında ayrıntılı bulabilirsiniz; aynı desenler burada da işe yarar.
Watch ile bind mount arasındaki fark
Compose, bir host dizinini container içine bağlamanıza (bind mount) zaten izin verir. Belgeler watch'ı bunun yerine geçen bir şey olarak değil, container içinde geliştirme yapmaya özel bir tamamlayıcı olarak tanımlar. Asıl farkı ayrıntı düzeyidir: watch kurallarıyla izlenen ağacın içindeki belirli dosyaları veya dizinleri dışarıda bırakabilirsiniz; bunu bir bind mount ile pratik biçimde yapmak zordur.
Belgelerdeki tipik örnek Node.js projesindeki node_modules/ dizinidir. Bu dizini senkronize etmemek iki nedenle önerilir. Birincisi performans: çok sayıda küçük dosyadan oluşan ağaçlar bazı yapılandırmalarda yüksek disk G/Ç yükü oluşturur. İkincisi platform farkı: host işletim sistemi veya işlemci mimarisi container'dan farklıysa derlenmiş çıktılar paylaşılamaz. JavaScript yorumlanan bir dil olsa da npm paketleri taşınabilir olmayan yerel (native) kod içerebilir; bu yüzden host'taki node_modules klasörünü container'a taşımak sorun çıkarabilir.
| Özellik | Bind mount | Compose Watch |
|---|---|---|
| Tanım yeri | services.volumes | services.develop.watch |
| Dosya seçimi | Dizinin tamamı bağlanır | ignore ve include ile ince ayar |
| Bağımlılık değişince | Kendiliğinden bir şey olmaz | rebuild kuralı imajı yeniden derler |
| Yapılandırma değişince | Servisi elle yeniden başlatırsınız | sync+restart veya sync+exec |
| Hazır imajlı servisler | Kullanılabilir | İzlenmez, build gerekir |
| Asıl kullanım | Genel amaçlı dosya paylaşımı | Container içinde geliştirme |
Bind mount'un kendisini, -v ile --mount farkını ve SELinux etiketlerini Docker bind mount yazısı anlatır.
Ön koşullar: imajda olması gerekenler
Watch doğru çalışmak için imajın içinde bazı yaygın programlara ihtiyaç duyar. Belgelerin saydığı üç program stat, mkdir ve rmdir'dir; servis imajınızda bunların bulunduğundan emin olun. Çok küçültülmüş bir taban imajı seçtiyseniz bu kontrol özellikle önemlidir. Taban imajı seçiminin diğer boyutları için base image seçimi yazısına bakabilirsiniz.
İkinci koşul yazma izniyle ilgilidir: container'ın USER değeri hedef yola yazabilmelidir, çünkü Compose dosyaları o kullanıcı adına günceller. Yaygın kalıp, ilk içeriği Dockerfile içinde COPY ile container'a almak ve dosyaların sahibini COPY --chown ile uygulama kullanıcısı yapmaktır. Belgelerdeki örneğe dayanan bir Dockerfile şöyle görünür:
# Ayrıcalıksız bir kullanıcıyla çalış
FROM node:18
RUN useradd -ms /bin/sh -u 1001 app
USER app
# Bağımlılıkları kur
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
# Kaynak dosyaları uygulama dizinine kopyala
COPY --chown=app:app . /appBurada son satırdaki --chown=app:app olmasaydı kopyalanan dosyalar root'a ait olurdu ve app kullanıcısıyla çalışan container'a yapılan senkronizasyon izin hatasına takılabilirdi. COPY talimatının ayrıntıları için COPY ve ADD farkı yazısına bakın.
Eylemler: sync, rebuild, restart, sync+restart, sync+exec

Her watch kuralı en az bir path ve bir action ister; seçtiğiniz eyleme göre başka alanlar da kabul edilir veya zorunlu olur. Compose Develop belirtimi beş eylem tanımlar. Develop bölümünün kendisi Docker Compose 2.22.0 ve sonrasında kullanılabilir; belirtim bazı eylemler için ayrıca sürüm notu düşer.
| Eylem | Ne yapar | Ne zaman uygun |
|---|---|---|
| sync | Container çalışmaya devam eder, değişen dosyalar target yoluna kopyalanır | Hot reload destekleyen çatılar, kaynak kodu |
| rebuild | BuildKit ile yeni imaj derlenir, servis container'ı yenisiyle değiştirilir | Derlenen diller, package.json gibi bağımlılık dosyaları |
| restart | Servis container'ı yeniden başlatılır (Compose 2.32.0 ve sonrası) | Dosya kopyalamaya gerek olmayan durumlar |
| sync+restart | Dosyalar kopyalanır, ardından container yeniden başlatılır (Compose 2.23.0 ve sonrası) | nginx.conf, veritabanı yapılandırması |
| sync+exec | Dosyalar kopyalanır, ardından container içinde bir komut çalıştırılır (Compose 2.32.0 ve sonrası) | Servisi kesmeden yeniden yükleme komutu |
sync, belgelerin ifadesiyle "Hot Reload" veya benzeri bir özelliği olan çatılar için idealdir: dosya container içine kopyalanır, uygulamanın kendi izleyicisi değişikliği fark edip sayfayı yeniler. Birçok geliştirme senaryosunda sync kuralları bind mount'un yerine kullanılabilir.
rebuild seçildiğinde Compose BuildKit ile yeni bir imaj derler ve çalışan servis container'ını değiştirir. Davranış docker compose up --build <servis> çalıştırmakla aynıdır. Bağımlılık eklemek çalışırken yapılamayacağı için package.json veya requirements.txt gibi dosyalara bu eylem bağlanır. Her yeniden derlemede önceki imaj sürümü "dangling" (etiketsiz) kalır; Compose bu artık imajları varsayılan olarak her rebuild sonrasında siler. Saklamak isterseniz docker compose watch --prune=false kullanırsınız. Derlemelerin hızlı olması için Dockerfile katmanlarını önbelleğe uygun sıralamak önemlidir; bunun için build cache yazısına ve temel katman mantığı için Dockerfile yazma rehberine bakın.
sync+restart, imajı yeniden derlemeye gerek olmayan ama ana sürecin yeniden başlaması gereken yapılandırma değişiklikleri içindir. Belgeler örnek olarak bir veritabanı yapılandırmasını veya nginx.conf dosyasını verir. sync+exec ise dosyaları kopyaladıktan sonra container içinde belirttiğiniz komutu çalıştırır; örneğin servisi kesmeden yapılandırmayı yeniden yükleyen bir komut. Bu eylemin alt alanları exec altında tanımlanır:
command: Çalıştırılacak komut. Zorunludur; shell ya da exec biçiminde yazılabilir.user: Komutu çalıştıracak kullanıcı. Verilmezse ana servis komutunun kullanıcısı kullanılır.privileged: Komutun ayrıcalıklı erişimle çalışmasına izin verir.working_dir: Çalışma dizini. Verilmezse ana komutun çalışma dizini kullanılır.environment: Komut, servisin ortam değişkenlerini devralır; bu bölümle yenilerini ekler veya mevcutları ezersiniz.
path, target, ignore, include ve initial_sync
path, izlenecek kaynağın proje dizinine göre yoludur. Bu yolun altındaki, herhangi bir ignore kuralına uymayan her dosya değişikliği eylemi tetikler. target ise yolun container içinde nereye eşleneceğini belirler ve senkronizasyon yapan eylemlerde anlam taşır. Belgelerdeki eşleme örneği şöyledir: path: ./app/html iken ./app/html/index.html değişirse dosya target: /app/html için /app/html/index.html, target: /assets için /assets/index.html konumuna yazılır. Yani path altındaki göreli yapı target altında korunur.
ignore desenleri .dockerignore ile aynı sözdizimini kullanır: * dosya adında sıfır veya daha fazla karaktere, ? tek karaktere, */* adı ne olursa olsun iç içe iki klasöre, ** ise istenen sayıda iç içe klasöre uyar. Önemli ayrıntı: bu desenler proje dizinine değil, o kuralın path değerine göre yorumlanır. path: ./web ile yazılmış bir kuraldaki node_modules/ deseni web/node_modules/ dizinini dışarıda bırakır, kök dizindeki node_modules/ dizinini değil.
Bazen hangi dosyaların dışarıda kalacağını saymak yerine hangilerinin izleneceğini söylemek daha kolaydır. include alanı bunun içindir: yalnızca verdiğiniz desene uyan dosyalar kurala dahil edilir, sözdizimi ignore ile aynıdır. Burada sık yapılan bir YAML hatası vardır. Desen çoğunlukla * ile başlar ve YAML'da yıldızla başlayan değer bir takma ad (alias) referansı sayılır. Tırnaksız yazılmış bir include: *.go satırını Compose v5.5.1 şu hatayla reddetti:
docker compose config --quiet
go-yaml load error in composer at L7.C20: unknown anchor '.go' referencedÇözüm, belgelerin de önerdiği gibi deseni tırnak içine almaktır: include: "*.go".
initial_sync, sync ile başlayan eylemlerde kullanılır. Servisin container'ları zaten varsa Compose yeni bir watch oturumu başlamadan önce path altındaki dosyaların container içinde güncel olup olmadığını kontrol eder. Watch kapalıyken yerelde yaptığınız değişikliklerin container'a hiç ulaşmaması bu ayarla önlenir.
Örnek 1: Node.js ön yüzü için sync ve rebuild
Aşağıdaki dosya belgelerdeki temel örnekten uyarlandı. web/ altındaki kaynak dosyalar container'daki /app/web dizinine senkronize edilir, test dosyaları ve node_modules/ dışarıda kalır, package.json değişince imaj yeniden derlenir. Port yalnızca 127.0.0.1 adresine yayınlanır; geliştirme sunucusunu dış dünyaya açmamak için bu iyi bir varsayılandır (ayrıntı: Docker port yayınlama).
services:
web:
build: .
command: npm start
ports:
- "127.0.0.1:3000:3000"
develop:
watch:
- action: sync
path: ./web
target: /app/web
initial_sync: true
ignore:
- node_modules/
- "*.test.js"
- action: rebuild
path: package.jsondocker compose up --watch çalıştırdığınızda Compose önce kök dizindeki Dockerfile'dan imajı derler ve web container'ını başlatır. Servis ayağa kalktıktan sonra izleme başlar. ./web/App.jsx dosyasını kaydettiğinizde dosya /app/web/App.jsx konumuna kopyalanır ve Webpack, Vite gibi bir paketleyicinin anlık modül yenilemesi uygulamayı yeniden başlatmadan günceller. package.json değiştiğinde ise yeni bağımlılık çalışan container'a eklenemeyeceği için imaj yeniden derlenir ve container yeniden oluşturulur. Aynı kalıp Python ve Flask gibi başka çatılara da uyar: kaynak dosyalar senkronize edilir, requirements.txt değişikliği yeniden derleme tetikler.
Örnek 2: nginx yapılandırması ve Go arka ucu
İkinci örnek üç farklı eylemi bir arada gösterir. nginx yapılandırma dosyası değişince dosya kopyalanıp container yeniden başlatılır; etc/config dizini değişince dosyalar kopyalanıp container içinde nginx -s reload çalıştırılır; Go arka ucunda ise yalnızca .go uzantılı dosyalar yeniden derleme tetikler.
services:
web:
build: .
develop:
watch:
- action: sync+restart
path: ./proxy/nginx.conf
target: /etc/nginx/conf.d/default.conf
- action: sync+exec
path: ./etc/config
target: /etc/config/
exec:
command: nginx -s reload
user: root
backend:
build:
context: backend
develop:
watch:
- action: rebuild
path: ./backend/src
include: "*.go"Bu dosyadaki exec.user: root satırı, yeniden yükleme komutunun ana süreçten farklı bir kullanıcıyla çalışabileceğini gösterir. backend servisinde target yoktur, çünkü rebuild dosya kopyalamaz; imajı baştan derler. Her iki örnek dosya da docker compose config --quiet ile doğrulandı ve hatasız (çıkış kodu 0) geçti.
Watch'ı çalıştırmak
Watch modunu iki yoldan açabilirsiniz. İlki up komutuna bayrak eklemektir; bu durumda uygulama logları ile derleme ve senkronizasyon olayları aynı terminalde akar. İkincisi ayrı watch komutudur; belgeler bunu, uygulama loglarının yeniden derleme loglarıyla ve dosya senkronizasyon olaylarıyla karışmasını istemediğinizde önerir.
docker compose up --watch
# Ya da logları ayrı tutmak için
docker compose watch
# Yeniden derlemelerde eski imajları silmeden
docker compose watch --prune=falseDocker Desktop ile gelen Compose kurulumlarında COMPOSE_MENU değişkeni varsayılan olarak açıktır ve terminalde gösterilen gezinme menüsünden watch modunu açabilirsiniz; Desktop dışından kurulan Compose'ta bu değişkenin varsayılanı kapalıdır. Kurulum farkları için Compose eklentisi kurulumu yazısına bakın.
Bir kural yazdıktan sonra ilk iş dosyayı doğrulamaktır. docker compose config --quiet geçerli bir dosyada hiçbir şey yazmadan 0 koduyla çıkar. Yanlış bir eylem adı yazdığımız denemede Compose v5.5.1 hatayı açıkça bildirdi: services.web.develop.watch.0.action value must be one of 'rebuild', 'sync', 'restart', 'sync+restart', 'sync+exec'. Bu ileti hem yazım hatasını yakalar hem de kullandığınız sürümün hangi eylemleri tanıdığını gösterir.
docker compose config --quietSık yapılan hatalar

- Hazır imajlı servise watch yazmak.
imageile çekilen servislerde değişiklik izlenmez; watch için servisinbuildile yerel kaynaktan derlenmesi gerekir. - node_modules dizinini senkronize etmek. Hem disk yükünü artırır hem de host ile container farklı platformdaysa yerel modüller çalışmayabilir. Kuralda
ignoreile dışarıda bırakın. - path içinde glob kullanmak.
pathglob desteklemez; dosya filtrelemek içinincludeveyaignorekullanın. - include desenini tırnaksız yazmak. Yıldızla başlayan değer YAML takma adı sanılır ve dosya yüklenemez.
- ignore yolunu proje köküne göre düşünmek. Desenler kuralın kendi
pathdeğerine göredir. - Container kullanıcısının yazamadığı hedef.
USERhedef dizine yazamıyorsa senkronizasyon başarısız olur; dosya sahipliğiniCOPY --chownile ayarlayın. - Bağımlılık dosyasını sync ile eşlemek. Yeni bir paket çalışan container'a dosya kopyalayarak kurulmaz; bağımlılık dosyalarını
rebuildkuralına bağlayın.
Sık Sorulan Sorular
docker compose up --watch ile docker compose watch arasında fark var mı?
İkisi de aynı develop.watch kurallarını uygular. Fark çıktıdadır: up --watch uygulama loglarını derleme ve senkronizasyon olaylarıyla aynı akışta gösterir, ayrı watch komutu ise bu olayları uygulama loglarından ayrı tutmak isteyenler için önerilir.
Watch, bind mount kullanmayı tamamen bırakmamı mı gerektirir?
Hayır. Belgeler watch'ı bind mount'un yerine geçen değil, onu tamamlayan bir özellik olarak tanımlar. Birçok geliştirme senaryosunda sync kuralları bind mount yerine kullanılabilir, ama hangisinin uygun olduğu projeye bağlıdır.
Rebuild sonrası biriken etiketsiz imajlar ne olur?
Compose, yeniden derleme sonrasında boşta kalan eski imaj sürümlerini varsayılan olarak siler. Saklamak isterseniz --prune=false bayrağını kullanın. Diğer disk temizliği konuları için Docker prune yazısına bakın.
Watch bir hazır imajı (örneğin nginx:latest) izleyebilir mi?
Hayır. Watch yalnızca build özniteliğiyle yerel kaynaktan derlenen servisleri izler. Hazır bir imajın yapılandırmasını değiştirmek istiyorsanız kendi Dockerfile'ınızı yazıp o imajdan türetebilir veya yapılandırmayı Compose configs ile verebilirsiniz.
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 · Docker Compose başlangıç rehberi · Docker Compose rehberi · Docker bind mount · Build context ve .dockerignore · Build cache