Docker Compose Watch: Feedback Instan untuk Dev Container Lokal

Foto oleh Florian Olivo
Docker Compose Watch adalah fitur yang mengamati file di host dan menyalin perubahan satu arah ke container yang sedang berjalan tanpa memerlukan rebuild penuh. Fitur ini resmi GA di Compose v2.22.0 yang dibundel dengan Docker Desktop 4.24. Jika Anda pernah update Docker sejak akhir 2023, fiturnya sudah tersedia.
Tiga action-nya adalah sync, rebuild, dan sync+restart. Gunakan sync untuk source code di framework dengan hot reload seperti NestJS dengan webpack HMR, Next.js, Vite, atau nodemon. Gunakan rebuild untuk manifest dependency seperti package.json, lockfile, dan Dockerfile itu sendiri. Gunakan sync+restart untuk file konfigurasi yang dibaca sekali saat boot, seperti file .env atau nginx.conf, di mana image-nya tidak masalah tapi prosesnya perlu start ulang.
Compose Watch melakukan sync satu arah dari host ke container, menjaga node_modules tetap di dalam container yang dibangun untuk Linux, otomatis memfilter file temp editor, dan men-debounce save beruntun menjadi transfer batch. Bind mount bersifat dua arah secara default sehingga tulisan dari container bisa mengotori tree di host dan menyebabkan konflik node_modules kecuali ditambahkan trik anonymous volume. Di macOS dan Windows, bind mount juga membayar penalti translasi filesystem lewat VM yang memperlambat operasi berat file.
Watch hanya berlaku untuk service yang memiliki atribut build; service dengan hanya key image akan diabaikan tanpa peringatan. Sync juga membutuhkan binary stat, mkdir, dan rmdir di dalam image container, sehingga image distroless dan ultra-minimal perlu varian dev berbasis tag slim atau alpine. Selain itu, jangan arahkan action sync ke package.json dengan harapan dependency ikut terinstall — sync hanya menyalin file, jadi manifest dependency harus menggunakan action rebuild.
Penulis mengukur loop di codebase NestJS ukuran menengah yang turun dari sekitar 45 detik per perubahan dengan rebuild penuh menjadi di bawah dua detik menggunakan sync dikombinasikan dengan webpack HMR. Tidak seperti bind mount, peningkatan kecepatan ini tidak mengorbankan fidelitas environment, sehingga image development tetap selaras dengan perilaku aplikasi di production.

Foto oleh Florian Olivo
Bertahun-tahun workflow container lokal saya punya pajak di setiap perubahan: edit file, pindah ke terminal, jalankan docker compose up --build, tunggu tiga puluh detik sampai dua menit, lalu cek browser. Kalikan dengan sekitar delapan puluh perubahan yang saya buat dalam satu sore yang fokus, dan saya membuang banyak waktu hanya untuk menunggu rebuild. Docker Compose Watch menghapus pajak itu hampir seluruhnya, dan fiturnya sudah ada di binary Compose yang Anda pakai sekarang.
Jawaban singkat untuk Anda yang sedang mencari: tambahkan blok develop.watch ke compose.yaml, deklarasikan path mana yang harus sync, rebuild, atau sync+restart, lalu jalankan docker compose up --watch. Compose Watch resmi GA di Compose v2.22.0 (dibundel dengan Docker Desktop 4.24), jadi kalau Anda pernah update Docker sejak akhir 2023, fiturnya sudah tersedia. Di artikel ini saya akan membahas cara saya memakainya untuk setup API NestJS plus worker, di mana ia mengalahkan bind mount, dan gotcha yang sempat menggigit saya di proyek nyata.
Sebelum Watch, ada dua opsi untuk kode live di dalam container, dan keduanya punya sisi tajam:
Compose Watch mengambil jalan ketiga: ia mengamati file di host dan menyalin perubahan satu arah ke container yang sedang berjalan. Image Anda tetap menjadi satu-satunya sumber kebenaran untuk dependency dan library sistem, sementara source code mengalir masuk saat Anda menekan save. Perubahan di sisi container tidak pernah bocor balik ke host, dan itu persis arah trust yang Anda inginkan saat development.
Setiap aturan watch memasangkan sebuah path dengan sebuah action. Memilih action yang tepat per path adalah sumber percepatan sesungguhnya, karena action termurah yang tetap menghasilkan container yang benar adalah pemenangnya.
| Action | Apa yang dilakukan | Kapan saya memakainya |
|---|---|---|
| sync | Menyalin file yang berubah ke container berjalan di path target, tanpa me-restart apa pun. | Source code di framework apa pun dengan hot reload: NestJS dengan webpack HMR, Next.js, Vite, script yang diawasi nodemon. |
| rebuild | Membangun ulang image dengan BuildKit dan mengganti container yang berjalan, seperti docker compose up --build untuk service itu. | package.json, lockfile, Dockerfile, apa pun yang terpanggang ke dalam layer image. Juga bahasa terkompilasi seperti Go di mana binary adalah artefaknya. |
| sync+restart | Menyalin file yang berubah, lalu me-restart proses container tanpa membangun ulang image. | File konfigurasi yang dibaca sekali saat boot: file .env, nginx.conf, ormconfig. Image-nya tidak masalah, prosesnya saja yang perlu start ulang. |
Berikut versi ringkas dari setup yang saya jalankan untuk API NestJS plus background worker. Perhatikan bagaimana setiap path mendapat action termurah yang masih layak, dan bagaimana ignore mencegah file test memicu sync yang sia-sia:
# compose.yaml — NestJS API + worker, watch-enabled
services:
api:
build: ./api
ports:
- "3000:3000"
develop:
watch:
# hot-reload source straight into the container
- path: ./api/src
target: /app/src
action: sync
# dependency changes need a real rebuild
- path: ./api/package.json
action: rebuild
# config tweak? just restart the process
- path: ./api/.env.development
action: sync+restart
target: /app/.env.development
worker:
build: ./worker
develop:
watch:
- path: ./worker/src
target: /app/src
action: sync
ignore:
- "**/*.spec.ts"Lalu jalankan semuanya dengan watch aktif:
docker compose up --watch
# or, to run watch without attaching logs:
docker compose watchPro tip: tetap pakai docker compose up --watch (satu terminal, log dan watch jadi satu) sampai stack Anda membesar. Dengan lebih dari tiga atau empat service, pisahkan log ke terminal lain dengan docker compose logs -f api supaya notifikasi sync tidak menenggelamkan output aplikasi Anda.
Saya masih sering ditanya kenapa tidak mount saja direktori source dan selesai. Ini perbandingan jujurnya setelah menjalankan kedua pendekatan di proyek klien dan aplikasi saya sendiri yang di-deploy ke VPS:
Compose Watch
Sync satu arah dari host ke container. node_modules tetap milik container, dibangun untuk Linux di dalam image. File temp editor otomatis difilter, dan save beruntun di-debounce menjadi transfer batch. Lingkungan dev sangat dekat dengan perilaku image production.
Bind mount
Dua arah secara default, jadi tulisan dari container mengotori tree di host Anda. node_modules host menutupi milik image kecuali Anda menambah trik anonymous volume. I/O lebih lambat lewat batas VM macOS/Windows. Masih oke untuk eksperimen cepat dan proyek satu service.
Aturan praktis saya: bind mount untuk prototyping sekali pakai, Compose Watch untuk apa pun yang punya Dockerfile dan kelak akan dirilis. Action sync memberi kecepatan feedback selevel bind mount sambil menjaga image sebagai kontrak, dan kontrak itulah yang membuat lompatan dari laptop ke node production Docker Swarm saya terasa membosankan, dan memang itu tujuannya.
Jangan arahkan action sync ke package.json dengan harapan dependency ikut terinstall. Sync hanya menyalin file; node_modules di container tidak akan berubah. Manifest dependency tempatnya di action rebuild, titik.
Compose Watch adalah salah satu fitur quality-of-life yang diam-diam balik modal dalam satu jam pertama. Loop terukur saya di codebase NestJS ukuran menengah turun dari sekitar 45 detik per perubahan dengan rebuild menjadi di bawah dua detik dengan sync plus webpack HMR, dan tidak seperti bind mount, saya tidak menukar fidelitas environment untuk mendapatkannya.
Kalau tim Anda masih rebuild image di setiap save, atau berkelahi dengan hantu node_modules dari bind mount, luangkan lima belas menit itu. Permukaan konfigurasinya cuma tiga action dan satu daftar ignore. Itu saja seluruh fiturnya, dan itu sudah cukup.
Sumber dan bacaan lanjutan