使用 Compose Watch

在 Docker Compose 版本 2.22.0 中引入
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 檔案時,它將非常有用

提示

使用 映象層快取多階段構建 來最佳化您的 Dockerfile,以便快速增量重建。

pathtarget

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

  1. compose.yaml 中向一個或多個服務新增 watch 部分。
  2. 執行 docker compose up --watch 以構建和啟動 Compose 專案並啟動檔案監視模式。
  3. 使用您首選的 IDE 或編輯器編輯服務原始檔。

提示

如果您不想將應用程式日誌與(重新)構建日誌和檔案系統同步事件混合在一起,也可以將 watch 與專用的 docker compose watch 命令一起使用。

正在尋找一個測試示例專案嗎?

檢視 dockersamples/avatars,或 Docker 文件的本地設定 以演示 Compose watch

反饋

我們正在積極徵求對該功能的反饋。請在 Compose 規範倉庫 中提供反饋或報告您可能發現的任何錯誤。

參考