vendor层总不命中缓存,根本原因是docker构建层顺序错误:必须最早单独copy composer.json和composer.lock(路径为./),紧接着run composer install;若copy . .在前、锁文件缺失或未提交、或vendor被提交后又被覆盖,均导致缓存必然失效。

为什么 vendor 层总不命中缓存?
根本不是 Composer 本身的问题,而是 Docker 构建层顺序写错了。只要 composer.json 和 composer.lock 不变,Docker 就能跳过 composer install ——但前提是它们必须最早被单独 COPY,且中间不能夹杂其他 COPY 或 RUN 指令。
-
COPY . .写在composer install前面:哪怕只改了README.md,整个vendor/层都会重建 -
composer.lock没提交到 Git 或本地缺失:Docker 每次都当新锁文件解析,版本浮动导致缓存失效 - 把
vendor/提交进 Git 后又COPY . .:直接覆盖掉前面装好的依赖,白跑一遍
怎么写 Dockerfile 才能让 composer install 缓存生效?
核心是分两步:先固化依赖声明,再注入业务代码。顺序错一步,缓存就全废。
- 第一组
COPY只包含:composer.json、composer.lock(路径必须是./,别带子目录) - 紧接着立刻
RUN composer install --no-dev --no-scripts --optimize-autoloader --prefer-dist - 之后再
COPY . .或按需COPY src/ ./src/等细粒度复制 - 别在
WORKDIR里git clone后再composer install:这会让所有依赖安装无法被缓存
哪些 composer install 参数会影响缓存稳定性?
参数不是越多越好,关键是排除运行时不确定因素。有些选项看似“增强”,实则破坏跨机器复用。
-
--no-dev:必须加。否则不同机器上可能装出不同phpunit版本,缓存层一碰就碎 -
--no-interaction:必须加。避免因交互提示或 prompt 差异触发重建 -
--optimize-autoloader:推荐加。它不影响缓存逻辑,但能减少后续RUN的副作用(比如生成autoload_files.php) -
--ignore-platform-reqs:禁用。它绕过 PHP 扩展检查,镜像在目标环境大概率跑不起来,缓存再稳也没用
国内环境还要注意什么?
网络不是主因,但配置错误会放大缓存失效的感知——比如每次构建都卡在 packagist.org 解析失败,你以为是缓存问题,其实是 DNS 或源没换。
- Dockerfile 中加:
RUN composer config -g repos.packagist composer https://mirrors.aliyun.com/composer/(别用已停用的 phpcomposer.com) - 别在
composer.json里硬编码镜像源:CI/CD 多项目共用时容易冲突,全局 config 更可控 - 如果挂载宿主机
~/.composer/cache到容器,确保路径存在、权限可写,且不是/tmp这类会被清理的目录
缓存是否生效,不取决于你加了多少 flag,而取决于 composer.lock 是否真实不变、是否最早被 COPY、以及有没有被其他指令意外污染。任何一步偏离这个链条,vendor 层就注定重建。











