docker中vendor层缓存失效的根本原因是copy顺序错误:必须最先copy composer.json和composer.lock,再run composer install,最后copy . .;若顺序错乱、锁文件缺失或被覆盖,缓存必然中断。

缓存失效不是 Composer 的锅,是 COPY 顺序和文件管理错了。只要 composer.json 和 composer.lock 不变、最早单独 COPY、且没被后续操作覆盖,composer install 层就一定能命中缓存。
为什么 vendor 层总不命中缓存?
根本原因不是 Composer 安装慢,而是 Docker 构建层被意外“打断”:
-
COPY . .放在composer install前面:哪怕只改一个空格或README.md,整个依赖安装层都会重建 -
composer.lock没提交到 Git 或本地被忽略:Docker 构建时拿不到锁文件,composer install只能解析composer.json,版本浮动导致结果不可复现 -
vendor/被COPY . .覆盖:本地开发若把vendor/提交进仓库,COPY 后直接冲掉前面装好的依赖目录 - 没用
.dockerignore:日志、临时文件、IDE 配置混入构建上下文,改变整体哈希值,连带让COPY composer.json层也失效
必须严格遵守的 COPY 顺序
顺序错一步,整条缓存链就断。以下三步缺一不可,且不能穿插其他指令:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
-
COPY composer.json composer.lock ./—— 必须是第一个COPY,路径必须是当前目录(./),不能写成/app/等相对路径变体 -
RUN composer install --no-dev --no-interaction --optimize-autoloader --no-scripts——--no-dev防止开发依赖引入环境差异;--no-interaction避免因交互提示中断或触发不同缓存分支 -
COPY . .—— 所有源码、配置、静态资源放在这一步;确保.dockerignore已排除vendor/、.git、node_modules等无关内容
BuildKit 的 cache mount 到底要不要开?
它加速的是包下载,不是 vendor 层复用。实际收益有限,还容易埋坑:
- CI 环境下多个 job 并发时,
id=composer-cache可能冲突,报错如Package foo has a PHP requirement incompatible with your PHP version - cache mount 不共享存储时,本地构建快、CI 构建慢,问题难复现
- 更可控的替代方案:CI 中挂载宿主机的
~/.composer/cache到容器内/root/.composer/cache,不依赖 BuildKit 特性 - 别为“看起来高级”加
--mount,90% 场景下分层 COPY + 锁文件稳定已足够
真正卡住缓存命中的,从来不是工具多先进,而是 composer.lock 是否真实存在、是否最早被复制、是否被后续 COPY 意外覆盖——这些细节在 CI 日志里往往只体现为一行 “CACHED” 或 “REBUILDING”,但背后全是构建时间的倍增。










