使用 Compose Watch

Docker Compose 版本 2.22.0 中引進

當您編輯和儲存程式碼時,watch 屬性會自動更新並預覽您正在執行的 Compose 服務。對於許多專案,這可以在 Compose 執行後啟用免動手開發工作流程,因為服務會在您儲存工作時自動更新自身。

watch 遵守下列檔案路徑規則

  • 所有路徑均相對於專案目錄
  • 遞迴監視目錄
  • 不支援 Glob 模式
  • 套用 .dockerignore 中的規則
    • 使用 ignore 選項定義要忽略的其他路徑(語法相同)
    • 常見 IDE(Vim、Emacs、JetBrains 等)的暫存/備份檔案會自動忽略
    • .git 目錄會自動忽略

您不需要為 Compose 專案中的所有服務開啟 watch。在某些情況下,只有專案的一部分(例如 Javascript 前端)可能適合自動更新。

Compose Watch 設計用於使用 build 屬性從本機原始碼建置的服務。它不會追蹤依賴 image 屬性指定的預建映像檔的服務變更。

Compose Watch 與繫結掛載的比較

Compose 支援在服務容器內共用主機目錄。監看模式不會取代此功能,但作為專門適用於在容器中開發的夥伴而存在。

更重要的是,watch 允許比繫結掛載更精細的粒度。監看規則允許您忽略受監視樹狀結構中的特定檔案或整個目錄。

例如,在 JavaScript 專案中,忽略 node_modules/ 目錄有兩個好處

  • 效能。具有許多小檔案的檔案樹狀結構在某些設定中可能會導致高 I/O 負載
  • 多平台。如果主機作業系統或架構與容器不同,則無法共用已編譯的構件

例如,在 Node.js 專案中,不建議同步 node_modules/ 目錄。即使 JavaScript 是直譯的,npm 套件也可能包含無法跨平台移植的原生程式碼。

設定

watch 屬性定義了一系列規則,這些規則根據本機檔案變更控制自動服務更新。

每個規則都需要一個 path 模式和在偵測到修改時要採取的 actionwatch 有兩種可能的動作,根據 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 作為其指令,然後啟動應用程式的開發版本,並在 bundler(Webpack、Vite、Turbopack 等)中啟用熱模組重新載入。

服務啟動後,監看模式會開始監控目標目錄和檔案。然後,只要 web/ 目錄中的原始碼檔案發生變更,Compose 就會將檔案同步到容器內 /src/web 下的對應位置。例如,./web/App.jsx 會被複製到 /src/web/App.jsx

複製完成後,bundler 會更新正在執行的應用程式,無需重新啟動。

與原始碼檔案不同,新增新的依賴項無法即時完成,因此只要 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

  1. compose.yaml 中的一個或多個服務中新增 watch 區段。
  2. 執行 docker compose up --watch 來建置和啟動 Compose 專案,並啟動檔案監看模式。
  3. 使用您慣用的 IDE 或編輯器編輯服務原始碼檔案。

注意事項

如果您不希望應用程式日誌與(重新)建置日誌和檔案系統同步事件混在一起,也可以搭配專用的 docker compose watch 指令使用監看功能。

小技巧

查看 dockersamples/avatarsDocker 文件的本地設定 以取得 Compose watch 的示範。

意見回饋

我們正積極尋求有關此功能的意見反應。請在 Compose 規格儲存庫 中提供意見反應或回報您可能發現的任何錯誤。

參考