<p>核心是启用BuildKit并严格分层:先全局启用DOCKER_BUILDKIT=1,再在Dockerfile中用# syntax=docker/dockerfile:1声明,builder阶段用--mount挂载composer缓存,COPY composer.json/lock前置且不插入RUN指令,final阶段仅COPY必要产物并确保版本与路径一致。</p>

用 docker compose build 配合多阶段构建加速交付,核心不是“多写几个 FROM”,而是让构建过程真正解耦、可缓存、并行且轻量。关键在 Dockerfile 设计 + Compose 配置 + 构建引擎协同。
确保 BuildKit 全局启用
BuildKit 是并行、缓存挂载、依赖图分析的基础。没它,多阶段只是体积变小,速度未必提升。
- 终端中执行:
export DOCKER_BUILDKIT=1(临时)或写入 shell 配置文件(长期) - Compose 构建时自动识别该变量,无需额外参数
- 验证是否生效:运行
docker compose build,输出中看到#1 [internal] load build definition...即表示已启用
多阶段 Dockerfile 必须严格分层
阶段划分不是为了好看,而是为了让每一层缓存更稳定、更精准。尤其对 PHP/Node/Go 等依赖密集型项目:
-
builder 阶段必须与 runtime 阶段使用完全一致的 PHP/Node/Go 小版本(例如都用
php:8.1-cli-bullseye,而非 builder 用php:8.1、final 用php:8.1-fpm-slim—— 小版本差异可能导致扩展缺失或 autoloader 失效) -
COPY 顺序不可颠倒:先
COPY composer.json composer.lock ./,再RUN composer install --no-dev --optimize-autoloader --classmap-authoritative;中间不能插任何 RUN 指令(如 chmod、mkdir),否则破坏缓存链 -
final 阶段只保留运行必需内容:用
COPY --from=builder /app/vendor /app/vendor,同时确保两阶段WORKDIR完全一致(如均为/app),避免路径错位导致autoload.php找不到
Compose 中显式控制构建上下文与参数
避免默认行为拖慢流程。在 docker-compose.yml 的 build 块中主动干预:
- 指定
dockerfile:路径,不依赖默认名,便于管理不同环境的构建变体 - 通过
args:传入构建时变量(如PHP_VERSION),实现同一 Dockerfile 复用多版本 - 若服务间无强依赖,
docker compose build默认已并行(BuildKit 启用后),无需加--parallel;但可配合depends_on明确逻辑顺序,防止误触发
缓存要“挂得准、用得稳”
Composer 包下载是最大瓶颈,靠层缓存不够,需挂载专用缓存区:
- Dockerfile 开头加:
# syntax=docker/dockerfile:1 - 在 builder 阶段的 RUN 指令中使用:
RUN --mount=type=cache,target=/root/.composer/cache composer install ... - 国内环境建议在 builder 阶段追加:
RUN composer config -g repos.packagist composer https://mirrors.aliyun.com/composer/ - 避免在 final 阶段残留
/root/.composer或未清理的 dev 依赖(--no-dev必须加)


















