根本原因是Docker未保留~/.composer/cache且COPY顺序错误:必须先单独COPY composer.json和composer.lock,再RUN composer install,否则代码微调即导致vendor层重建;挂载缓存需确保路径、权限、PHP版本、镜像源、lock哈希五者一致。

为什么Docker里composer install总要重下包
根本原因不是Composer慢,而是每次构建都丢掉了上一次的缓存。Docker默认不保留~/.composer/cache,所有ZIP包、元数据、dist缓存全被丢弃,等于每次都在裸跑。更糟的是,如果composer.json和composer.lock在COPY . .之后才复制,那哪怕只改一行代码,整个vendor/也会被重建。
Dockerfile里必须把依赖文件提前COPY
这是复用层缓存的前提。只要composer.json和composer.lock没变,后续RUN composer install就能命中缓存。
-
COPY composer.json composer.lock ./必须放在COPY . .之前 - 不要写成
COPY . .再RUN composer install——这会让任何源码变更都失效缓存 - 若项目用多阶段构建,可在builder阶段完成
composer install,再COPY --from=builder /app/vendor /app/vendor
挂载缓存目录时注意路径和权限
光挂~/.composer/cache不够,还得确保它真被用上,且不因权限或路径冲突失效。
- 宿主机缓存路径建议用绝对路径,比如
/home/user/.composer-cache,避免~在容器内解析失败 - Docker run时挂载:
-v /home/user/.composer-cache:/root/.composer/cache(镜像用户是root)或-v /home/user/.composer-cache:/var/www/.composer/cache(对应非root用户) - 验证是否生效:进容器执行
composer config -g cache-dir,输出应为挂载的目标路径 - 常见错误:
file_put_contents(/tmp/): failed to open stream,说明临时目录不可写,此时需显式设COMPOSER_CACHE_DIR环境变量指向可写路径
CI/CD和本地开发的缓存key不能混用
缓存不是“有就行”,必须保证PHP版本、镜像源地址、composer.lock哈希三者一致,否则会加载错包甚至报Signature mismatch。
- CI中用
cache-key: composer-${{ hashFiles('**/composer.lock') }}-${{ env.PHP_VERSION }}这类组合key - 本地开发慎用全局
--no-dev,因为CI可能需要dev依赖做静态分析;建议用ENV COMPOSER_NO_DEV=1统一控制 - 每次换PHP小版本(如8.3.0→8.3.1)都该清一次缓存,否则opcache类映射可能失效
composer.lock哈希变了,缓存就只是占磁盘的废文件。


















