使用 Compose Watch
watch
属性会在您编辑和保存代码时自动更新和预览运行中的 Compose 服务。对于许多项目而言,这使得 Compose 运行后无需动手操作即可完成开发工作流程,因为服务会在您保存工作时自动更新自身。watch
遵循以下文件路径规则
- 所有路径相对于项目目录
- 递归监视目录
- 不支持通配符模式
- 来自
.dockerignore
的规则适用- 使用
ignore
选项定义要忽略的其他路径(语法相同) - 自动忽略常见 IDE(Vim、Emacs、JetBrains 等)的临时/备份文件
- 自动忽略
.git
目录
- 使用
您无需为 Compose 项目中的所有服务开启 watch
。在某些情况下,可能只适合将项目的一部分(例如 Javascript 前端)进行自动更新。
Compose Watch 与绑定挂载
Compose 支持在服务容器内部共享主机目录。监视模式不会取代此功能,而是作为专门适用于在容器中进行开发的辅助工具。
更重要的是,watch
允许以比绑定挂载更细粒度的程度进行控制。监视规则让您忽略监视树中的特定文件或整个目录。
例如,在 JavaScript 项目中,忽略 node_modules/
目录有两个好处
- 性能。包含许多小文件的目录树会导致某些配置中的 I/O 负载过高
- 跨平台。如果主机操作系统或体系结构与容器不同,则无法共享已编译的构件
例如,在 Node.js 项目中,不建议同步 node_modules/
目录。即使 JavaScript 是解释型语言,npm
包也可能包含无法跨平台移植的原生代码。
配置
watch
属性定义了一组规则,这些规则根据本地文件更改控制自动服务更新。
每个规则都需要一个 path
模式和一个 action
,用于在检测到修改时执行。watch
有两种可能的动作,并且根据 action
,可能会接受或要求其他字段。
监视模式可与多种不同的语言和框架一起使用。特定的路径和规则因项目而异,但概念保持一致。
先决条件
为了正常工作,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 <svc>
相同。
重新构建非常适合编译型语言,或者作为对需要完全重新构建镜像的特定文件的修改的回退(例如 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.html
target: /app/static
->/app/static/index.html
target: /assets
->/assets/index.html
示例 1
此最小示例以以下结构为目标 Node.js 应用程序
myproject/
├── web/
│ ├── App.jsx
│ └── index.js
├── Dockerfile
├── compose.yaml
└── package.json
services:
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 等)中启用热模块重载。
服务启动后,监视模式开始监视目标目录和文件。然后,每当 web/
目录中的源文件发生更改时,Compose 会将文件同步到容器内 /src/web
下的相应位置。例如,./web/App.jsx
会被复制到 /src/web/App.jsx
。
复制后,捆绑器会更新正在运行的应用程序,无需重新启动。
与源代码文件不同,无法即时添加新的依赖项,因此每当 package.json
发生更改时,Compose 都会重新构建镜像并重新创建 web
服务容器。
此模式可用于许多语言和框架,例如 Python with Flask: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
- 在
compose.yaml
中向一个或多个服务添加watch
部分。 - 运行
docker compose up --watch
以构建和启动 Compose 项目并启动文件监视模式。 - 使用您首选的 IDE 或编辑器编辑服务源文件。
提示
如果您不想将应用程序日志与(重新)构建日志和文件系统同步事件混合在一起,也可以将 watch 与专用的
docker compose watch
命令一起使用。
正在寻找一个测试示例项目吗?
查看
dockersamples/avatars
,或 Docker 文档的本地设置 以演示 Composewatch
。
反馈
我们正在积极征求对该功能的反馈。请在 Compose 规范仓库 中提供反馈或报告您可能发现的任何错误。