689 字
3 分鐘

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:

compose.yaml
include:
- path: ./infra/compose.yaml
services:
web:
build: .
depends_on:
redis:
condition: service_healthy
infra/compose.yaml
services:
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 執行:

Terminal window
docker compose config
docker compose up -d
docker compose ps

第一個指令會輸出 Compose 解析後的 model,最適合確認 service 是否真的載入、路徑是否正確與變數是否被插值。之後再用 ps 檢查 healthcheck;只有 YAML 能通過不代表服務間真的能連線。

若你是把既有自架服務拆成多份 Compose,升級前的備份與還原邊界仍要先確認,可搭配 Dify 升級前的 Docker Compose 備份檢查 一起看。

參考資料:

Docker Docs:Use include to modularize Compose files

Docker Docs:How Compose works

Docker Compose include 怎麼拆檔:先釐清路徑、變數與名稱衝突
https://laplusda.com/posts/docker-compose-include-configuration/
作者
Zero
發佈於
2026-07-29
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。