With Docker Compose, when would you use `docker compose watch` with `sync` instead of a bind mount or `rebuild`, and what are its limits?
answer
- one-way copy into a running container
- ignore rules a mount cannot give
- dependency changes need the image
- binaries and a writable target
basics
~20 sUse watch sync when edited source should reach a running container quickly but selectively: it copies changed files one way into the container and honours ignore rules. Use rebuild for dependency or Dockerfile changes. Container-side writes never come back.
solid answer
~50 s`docker compose watch`, or `up --watch`, reads each service's `develop.watch` rules (Compose 2.22 and later) and reacts to changes under each `path`. `sync` copies changed files **one way** into the running container at `target` with no restart, which suits an app that hot-reloads; `sync+restart` also restarts the container, for config files; `sync+exec` runs a command after syncing (2.32 and later); `rebuild` rebuilds the image and recreates the container like `up --build <svc>`, for lockfile or Dockerfile changes. Compared with a bind mount, watch can **ignore** paths such as a dependency directory built for the container's platform, and it avoids routing every file read through host file sharing. The limits: files written inside the container never reach the host, the image needs `stat`, `mkdir` and `rmdir` and a user that can write `target`, `rebuild` needs a `build` section, and a `sync` path that is also bind-mounted is skipped with a warning.
code
yaml · 15 linesservices:
api:
build: ./api
develop:
watch:
- path: ./api/src
action: sync
target: /app/src
ignore:
- generated/
- path: ./api/config
action: sync+restart
target: /app/config
- path: ./api/dependencies.lock
action: rebuildgo deeper
Recall that docker compose watch reacts to file changes using develop.watch rules, and that sync copies files into the running container while rebuild rebuilds the image.
Explain the five actions and which change calls for which: source to sync, config to sync+restart, lockfile or Dockerfile to rebuild. Know that target is required for the sync actions.
Show why you would pick watch over a bind mount: ignore rules for platform-specific directories, less file-sharing I/O and one-way copy semantics, plus the image prerequisites that break sync.
Weigh watch as a team standard: one documented rule set instead of per-developer bind mounts, and the ongoing cost of keeping those rules in step with the Dockerfile as the project grows.
## The inner-loop problem Rebuilding an image for every one-line edit is slow. Bind-mounting the whole source tree has costs of its own: every file the container reads goes through host file sharing, and directories that must differ between host and container, such as a dependency directory holding native builds for the container's platform or generated output, get shared too. **Compose Watch**, available since Compose 2.22 and assumed here at Compose v5.5.1, is a third option: Compose watches host paths and applies a per-path **action** to the running service. ## How `develop.watch` works 1. You add a `develop.watch` list to a service. Each rule has a `path` (relative to the project directory and watched recursively), an `action`, and, for the sync actions, a `target` path inside the container. 2. `docker compose watch` builds and starts the services, unless you pass `--no-up`, and then watches. `docker compose up --watch` (`-w`) does the same while attached to the service logs; `--watch` cannot be combined with `--detach`. 3. On a change, Compose matches the file against the rules, skipping anything that matches the rule's `ignore` patterns, the build context's `.dockerignore`, `.git` directories and common editor temporary files. 4. It applies the action. After a `rebuild`, it removes the superseded dangling image unless you run `docker compose watch --prune=false`. ## The five actions | `action` | What Compose does | Use it for | |---|---|---| | `sync` | copies changed files to `target` in the running container | source an app hot-reloads | | `sync+restart` | syncs, then restarts the container | config files read at start-up | | `sync+exec` | syncs, then runs the rule's `exec.command` in the container | a reload or cache-clear command | | `restart` | restarts the container without copying anything | files already visible through a bind mount that the app reads only at start-up | | `rebuild` | rebuilds the image and recreates the container, like `docker compose up --build <svc>` | lockfiles, the Dockerfile, compiled code | `restart` and `sync+exec` arrived in Compose 2.32, so releases before it offer neither. ## Watch versus a bind mount - **Granularity:** rules can ignore paths inside the watched tree, while a bind mount shares everything under it. - **Performance:** only changed files are copied, instead of every read crossing host file sharing. - **Platform separation:** a dependency directory built for the container's platform stays in the image and is never overwritten from the host. - **Direction:** a bind mount is two-way, while `sync` is one-way, host to container. The Compose documentation presents watch as a companion to bind mounts, not a replacement. When a `sync` or `sync+restart` path is also declared as a bind mount on the same service, Compose warns and does not monitor that path. ## Limits and traps - **One way only.** Files the app writes inside the container, such as generated assets, stay there. - **Image prerequisites.** Sync copies an archive into the container and runs `rm -rf` there for deleted files; the documentation asks for `stat`, `mkdir` and `rmdir` in the image and a container user that can write to `target`. - **Validation.** `target` is required for `sync`, `sync+restart` and `sync+exec`, `sync+exec` needs an `exec.command`, and `rebuild` needs a `build` section and refuses `--no-build`. - **Rebuild is still a rebuild.** A `rebuild` rule is only as fast as the image build; watch shortens the loop for source, not for dependency changes. ## Choosing a mechanism per path 1. **Source that the app reloads on change:** `sync`. 2. **Configuration read only at start-up:** `sync+restart`, or `sync+exec` when the app has its own reload command. 3. **Anything installed or compiled during the image build,** such as dependencies from a lockfile: `rebuild`. 4. **Data that must flow both ways,** such as files the container generates for you to inspect: a bind mount. Rules are only needed on the services you edit, and `ignore` patterns are resolved relative to the rule's own `path`, not the project directory. ## A rule set for the API stack ```yaml services: api: build: ./api develop: watch: - path: ./api/src action: sync target: /app/src ignore: - generated/ - path: ./api/config action: sync+restart target: /app/config - path: ./api/dependencies.lock action: rebuild ``` Source edits appear in seconds, a config edit restarts the container, and only a dependency change pays for an image build. The `db` and `redis` services need no rules at all.
- What happens to files the API writes inside its container while `sync` is watching `./api/src`?They stay in the container. Sync is one-way: Compose copies files changed on the host into the container and deletes there the files you deleted on the host, but it never copies container-side writes back. If the host needs those files, use a bind mount for that directory or copy them out with `docker compose cp`.
- Why does `docker compose up -d --watch` fail?Watching is a foreground process that listens for file-system events, so Compose rejects `--watch` together with `--detach`. Run `docker compose up --watch` attached, or start the stack with `up -d` and run `docker compose watch --no-up` in another terminal.
- A teammate declares `./api/src` both as a bind mount and as a `sync` path. What happens?Compose warns that the path is also declared by a bind mount and does not monitor it for that service. The bind mount already exposes the files, so the sync rule adds nothing; choose one mechanism per path.
saying these in an interview costs you the question
- watch sync keeps host and container in two-way sync, like a bind mount.
- A sync rule quietly rebuilds the image in the background.
- A rebuild rule works on a service that has only image: and no build section.
- docker compose up -d --watch runs the watcher in the background.
- Once watch is on, dependency changes are picked up by sync alone.