使用 Compose Watch
watch 屬性可以在您編輯並儲存程式碼時,自動更新並預覽執行中的 Compose 服務。對於許多專案來說,一旦 Compose 啟動後,這能實現無需手動操作的開發工作流程,因為服務會在您儲存工作時自動更新。
watch 遵循以下檔案路徑規則:
- 除了忽略檔案的樣式外,所有路徑均相對於專案目錄。
- 目錄會被遞迴監控。
- 不支援萬用字元 (Glob patterns)。
.dockerignore中的規則同樣適用。- 使用
ignore選項可定義需要忽略的其他路徑(語法相同)。 - 常見 IDE(如 Vim、Emacs、JetBrains 等)的暫存檔/備份檔會被自動忽略。
.git目錄會被自動忽略。
- 使用
您不需要為 Compose 專案中的所有服務開啟 watch。在某些情況下,可能只有專案的一部分(例如 Javascript 前端)適合自動更新。
Compose Watch 專為使用 build 屬性從本地原始碼建構的服務而設計。它不會追蹤依賴於 image 屬性指定的預建映像檔的服務變更。
Compose Watch 與綁定掛載 (bind mounts) 的比較
Compose 支援將主機目錄共享到服務容器內部。Watch 模式並未取代此功能,而是作為專門適合容器開發的輔助工具存在。
更重要的是,watch 提供了比綁定掛載更細緻的控制。Watch 規則讓您可以忽略監控樹中的特定檔案或整個目錄。
例如,在 JavaScript 專案中,忽略 node_modules/ 目錄有兩個好處:
- 效能:在某些配置中,包含大量小型檔案的檔案樹可能會導致高 I/O 負載。
- 多平台:如果主機 OS 或架構與容器不同,則無法共享已編譯的成品。
例如,在 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(同步)
如果 action 設定為 sync,Compose 會確保您在主機上對檔案所做的任何變更,都會自動與服務容器內對應的檔案保持一致。
sync 非常適合支援「熱重載」(Hot Reload) 或類似功能的框架。
更一般地說,對於許多開發使用案例,sync 規則可用於取代綁定掛載。
Rebuild(重建)
如果 action 設定為 rebuild,Compose 會自動使用 BuildKit 建構一個新的映像檔,並取代執行中的服務容器。
其行為與執行 docker compose up --build <svc> 相同。
Rebuild 非常適合編譯語言,或作為需要完整映像檔重建的特定檔案(例如 package.json)修改時的備用方案。
Sync + Restart(同步並重新啟動)
如果 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)
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 等)中啟動已啟用熱模組重載 (Hot Module Reload) 的開發版本應用程式。
服務啟動後,watch 模式開始監控目標目錄和檔案。然後,每當 web/ 目錄中的原始碼檔案變更時,Compose 就會將該檔案同步到容器內 /src/web 下的對應位置。例如,./web/App.jsx 會被複製到 /src/web/App.jsx。
複製完成後,打包工具會更新執行中的應用程式,無需重新啟動。
在這種情況下,ignore 規則將應用於 myproject/web/node_modules/,而不是 myproject/node_modules/。
與原始碼檔案不同,新增依賴項無法即時完成,因此每當 package.json 變更時,Compose 都會重建映像檔並重新建立 web 服務容器。
許多語言和框架都可以遵循此模式,例如 Python 的 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 或編輯器編輯服務原始檔。
注意如果您不想將應用程式日誌與(重)建構日誌和檔案系統同步事件混在一起,也可以使用專用的
docker compose watch指令。
提示查看
dockersamples/avatars,或用於 Docker 文件 本地設定,以取得 Composewatch的示範。