Docker Compose include 怎麼拆檔:先釐清路徑、變數與名稱衝突
當 compose.yaml 同時塞進應用程式、資料庫、監控與開發工具,常見的反應是再加一個 -f compose.prod.yaml。這能覆寫設定,卻不一定適合把「可獨立維護的一組服務」拆出去。
Docker Compose 的 include 適合這個情境:主設定檔載入其他 Compose application,之後可直接引用其中的 service、network 或 volume。先確認 Compose 版本至少為 2.20.0;再把每份被引入檔案都當成有自己相對路徑與預設 .env 的小專案來檢查。
最小拆分方式
先把基礎服務放進 infra/compose.yaml,主專案只保留應用程式與 include:
include: - path: ./infra/compose.yaml
services: web: build: . depends_on: redis: condition: service_healthyservices: redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5載入後,web 可以直接依賴 redis;不需要把 service 再複製回主檔。這與 extends 的用途不同:include 匯入整份 Compose application,extends 則是讓某個 service 繼承另一個 service 的設定。
最容易錯的是相對路徑
短寫法會以被 include 檔案所在資料夾作為預設 project directory。因此 infra/compose.yaml 裡的 build: .、bind mount 路徑與預設 .env 都是相對於 infra/,不是根目錄。
需要明確指定時,改用長寫法:
include: - path: ./infra/compose.yaml project_directory: . env_file: - ./infra/defaults.env這不是「把所有環境變數集中」的捷徑。被 include 檔案的預設值可由主專案的環境覆寫;部署前仍應列出實際生效的值,避免 development 的 host、port 或 credential 名稱被意外帶到 production。
名稱衝突不會自動合併
include 完成後,Compose 會把資源帶入目前的 application model。若兩份檔案定義同名 resource,Compose 會顯示警告,而不是替你猜要怎麼 merge。這正是拆檔前要先定義所有權的原因:
| 類型 | 建議所有權 |
|---|---|
web、worker 與其環境變數 | 主專案 |
| database、cache、共用 network | 基礎服務檔 |
| 同名 service 的差異化覆寫 | 仍使用明確的 -f override,或先重新設計名稱 |
不要把同一個 redis 同時放在主檔與 infra 檔,再期待後讀取的設定贏得不透明的合併規則。
用 render 結果驗證,而不是只看 YAML
每次拆檔後,先在 repository root 執行:
docker compose configdocker compose up -ddocker compose ps第一個指令會輸出 Compose 解析後的 model,最適合確認 service 是否真的載入、路徑是否正確與變數是否被插值。之後再用 ps 檢查 healthcheck;只有 YAML 能通過不代表服務間真的能連線。
若你是把既有自架服務拆成多份 Compose,升級前的備份與還原邊界仍要先確認,可搭配 Dify 升級前的 Docker Compose 備份檢查 一起看。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。