使用 Compose Watch
watch 属性会在您编辑和保存代码时自动更新并预览您正在运行的 Compose 服务。对于许多项目,这使得一旦 Compose 运行起来,就可以实现免手动开发工作流,因为当您保存工作时,服务会自动更新。
watch 遵循以下文件路径规则
- 所有路径都相对于项目目录,除了忽略文件模式
- 目录被递归监视
- 不支持 glob 模式
- 应用
.dockerignore中的规则- 使用
ignore选项定义要忽略的其他路径(语法相同) - 常见 IDE(Vim、Emacs、JetBrains 等)的临时/备份文件会自动忽略
.git目录会自动忽略
- 使用
您不需要为 Compose 项目中的所有服务都开启 watch。在某些情况下,只有项目的一部分(例如 JavaScript 前端)可能适合自动更新。
Compose Watch 旨在与使用 build 属性从本地源代码构建的服务配合使用。它不会跟踪依赖于 image 属性指定预构建镜像的服务所做的更改。
Compose Watch 与绑定挂载
Compose 支持在服务容器内共享主机目录。Watch 模式不取代此功能,而是作为专门适用于容器内开发的伴侣而存在。
更重要的是,watch 允许比绑定挂载更细粒度的控制。Watch 规则允许您忽略监视树中的特定文件或整个目录。
例如,在 JavaScript 项目中,忽略 node_modules/ 目录有两个好处:
- 性能。在某些配置中,包含许多小文件的文件树可能会导致高 I/O 负载。
- 多平台。如果主机操作系统或架构与容器不同,则无法共享编译后的工件。
例如,在 Node.js 项目中,不建议同步 node_modules/ 目录。即使 JavaScript 是解释型语言,npm 包也可能包含不可跨平台移植的本机代码。
配置
watch 属性定义了一组规则,这些规则根据本地文件更改控制服务的自动更新。
每个规则都需要一个 path 模式和在检测到修改时要执行的 action。对于 watch 有两种可能的操作,并且根据 action,可能会接受或要求附加字段。
Watch 模式可以与许多不同的语言和框架一起使用。具体路径和规则会因项目而异,但概念保持不变。
先决条件
为了正常工作,watch 依赖于常见的可执行文件。确保您的服务镜像包含以下二进制文件:
- stat
- mkdir
- rmdir
watch 还要求容器的 USER 能够写入目标路径,以便它能够更新文件。一种常见模式是使用 Dockerfile 中的 COPY 指令将初始内容复制到容器中。为确保此类文件由配置的用户拥有,请使用 COPY --chown 标志。
# Run as a non-privileged user
FROM node:18
RUN useradd -ms /bin/sh -u 1001 app
USER app
# Install dependencies
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
# Copy source files into application directory
COPY --chown=app:app . /app操作
同步
如果 action 设置为 sync,Compose 会确保对主机上文件所做的任何更改都会自动与服务容器中对应的文件匹配。
sync 非常适合支持“热重载”或类似功能的框架。
更一般地说,sync 规则可以替代绑定挂载用于许多开发用例。
重建
如果 action 设置为 rebuild,Compose 会自动使用 BuildKit 构建新镜像并替换正在运行的服务容器。
其行为与运行 docker compose up --build 相同。
重建非常适合编译语言,或者作为需要完整镜像重建的特定文件(例如 package.json)修改的备用方案。
同步 + 重启
如果 action 设置为 sync+restart,Compose 会将您的更改与服务容器同步并重启它们。
当配置文件更改且您不需要重建镜像,而只需重启服务容器的主进程时,sync+restart 是理想的选择。例如,当您更新数据库配置或 nginx.conf 文件时,它会很好地工作。
提示
path 和 target
target 字段控制路径如何映射到容器中。
对于 path: ./app/html 和对 ./app/html/index.html 的更改
target: /app/html->/app/html/index.htmltarget: /app/static->/app/static/index.htmltarget: /assets->/assets/index.html
忽略
ignore 模式相对于当前 watch 操作中定义的 path,而不是项目目录。在下面的示例 1 中,忽略路径将相对于 path 属性中指定的 ./web 目录。
示例 1
这个最小示例针对具有以下结构的 Node.js 应用程序:
myproject/
├── web/
│ ├── App.jsx
│ ├── index.js
│ └── node_modules/
├── Dockerfile
├── compose.yaml
└── package.jsonservices:
web:
build: .
command: npm start
develop:
watch:
- action: sync
path: ./web
target: /src/web
ignore:
- node_modules/
- action: rebuild
path: package.json在此示例中,当运行 docker compose up --watch 时,将使用从项目根目录中的 Dockerfile 构建的镜像启动 web 服务的容器。web 服务运行 npm start 作为其命令,然后启动一个开发版本的应用程序,并在捆绑器(Webpack、Vite、Turbopack 等)中启用热模块重载。
服务启动后,watch 模式开始监视目标目录和文件。然后,只要 web/ 目录中的源文件发生更改,Compose 就会将文件同步到容器内 /src/web 下的相应位置。例如,./web/App.jsx 被复制到 /src/web/App.jsx。
复制后,捆绑器会更新正在运行的应用程序而无需重新启动。
在这种情况下,ignore 规则将应用于 myproject/web/node_modules/,而不是 myproject/node_modules/。
与源代码文件不同,添加新依赖项无法即时完成,因此只要 package.json 更改,Compose 就会重建镜像并重新创建 web 服务容器。
这种模式可以应用于许多语言和框架,例如带有 Flask 的 Python:Python 源文件可以同步,而 requirements.txt 的更改应该触发重建。
示例 2
调整上一个示例以演示 sync+restart
services:
web:
build: .
command: npm start
develop:
watch:
- action: sync
path: ./web
target: /app/web
ignore:
- node_modules/
- action: sync+restart
path: ./proxy/nginx.conf
target: /etc/nginx/conf.d/default.conf
backend:
build:
context: backend
target: builder此设置演示了如何在 Docker Compose 中使用 sync+restart 操作来高效开发和测试带有前端 Web 服务器和后端服务的 Node.js 应用程序。该配置确保应用程序代码和配置文件的更改快速同步和应用,并在需要时重新启动 web 服务以反映更改。
使用 watch
- 将
watch部分添加到compose.yaml中的一个或多个服务。 - 运行
docker compose up --watch以构建和启动 Compose 项目并启动文件监视模式。 - 使用您喜欢的 IDE 或编辑器编辑服务源文件。
注意如果您不想让应用程序日志与(重新)构建日志和文件系统同步事件混在一起,Watch 也可以与专用的
docker compose watch命令一起使用。
提示查看
dockersamples/avatars或 Docker docs 的本地设置,以演示 Composewatch。