feat(docker): 移除 bind mount,程式碼與 vendor 烘進 image
Run Tests / test (pull_request) Successful in 32s

Dockerfile 改 multi-stage(app + web),app/scheduler/queue-worker/
reverb/nginx 五個服務都不再依賴 ./:/var/www bind mount 取得程式碼;
nginx 改本地 build 從 app 階段 COPY --from 取得 public/,public/storage
symlink 在兩階段各自於 build 時建立。docker-compose.yml 新增具名 volume
storage-app-public 讓上傳檔案跨 image 重建保留;env_file: 取代原本
bind mount 帶入 .env 的方式,只給四個 Laravel runtime 服務。
compose.override.yml 補上開發用 bind mount 維持改 code 立即生效;
docker-entrypoint.sh 收斂到只剩目錄權限設定,migration/cache/swagger
移到 deploy.yml 統一負責,避免職責重疊。

實作驗證時發現並修復三個規劃階段沒預見的問題:app 服務的 build: 缺
target: app 導致預設建到最後一個 stage(image 實際變成 nginx);
.dockerignore 需排除本機既有的 public/storage 符號連結(Windows 上
會讓 build context 打包失敗);env_file: 讓 .env 全部變數變成真實
環境變數、蓋掉 phpunit.xml 的測試隔離設定,已擴大 tests/bootstrap.php
的強制覆蓋清單修復(239 tests 全綠)。

本機 dev 模式與 production 模式(無 override)皆完整驗證:healthcheck、
migration/cache/swagger、上傳檔案持久性、nginx 獨立於 app 服務靜態檔
與 storage 檔案、.env 熱更新、nginx 無 .env 存取權。

openspec change: bake-image-remove-bind-mount

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0142LC1kQb8EyV59TjHDkhWS
This commit is contained in:
2026-08-04 16:59:18 +08:00
parent 3b0cdf96d8
commit 6a7d98b0fe
12 changed files with 226 additions and 168 deletions
@@ -78,6 +78,17 @@
- **WHEN** 執行 `docker compose -f docker-compose.yml up -d`
- **THEN** 五個服務容器內的 `/var/www` 內容與 image build 時內嵌的內容一致,即使主機端程式碼目錄被刪除,容器仍正常運作
### Requirement: 每個 compose service 明確指定 multi-stage build target
`docker-compose.yml` 中依賴這份 multi-stage `Dockerfile` 建置的每一個服務(`app``nginx`SHALL 在其 `build:` 設定明確指定 `target:``app` 服務指定 `target: app``nginx` 服務指定 `target: web`),不得省略。
#### Scenario: app 服務建置出的是 php-fpm image 而非 nginx
- **WHEN** 執行 `docker compose build app`
- **THEN** 建置完成的 `cfdive-platform` image 其 entrypoint/預設指令為啟動 php-fpm,而非 nginx`docker image inspect cfdive-platform` 確認 `Config.Cmd``["php-fpm"]`
#### Scenario: 省略 target 會建到 Dockerfile 最後一個 stage
- **WHEN** 某服務的 `build:` 未指定 `target:`
- **THEN** Docker 依規範建置到 Dockerfile 中定義的最後一個 stage,可能與該服務實際需要的 stage 不同——此為本次 multi-stage 化後所有服務都必須明確宣告 target 的原因
### Requirement: 本機開發環境透過 override 疊加 bind mount
`compose.override.yml` SHALL 為 `app``nginx``scheduler``queue-worker``reverb` 定義 `./:/var/www` bind mount,供本機開發時「改 code 立即生效」使用;此 override 檔案不影響 production compose 行為。