GitLab CI 中 Composer 缓存常失效的根本原因是未同时缓存 vendor/、~/.composer/cache/ 和 ~/.composer/files/ 三处路径,且 cache:key 配置不当(如误用 $CI_COMMIT_REF_SLUG 而非 $CI_JOB_NAME+$CI_COMMIT_SHA),导致每次构建重复下载与解压。

GitLab CI 中 Composer 缓存为什么经常失效?
根本原因不是 composer install 本身慢,而是每次 CI 构建都从零下载依赖包、解压、生成 autoload 文件。缓存失效常见于:composer.lock 变更但缓存键未更新、cache:key 用错变量(比如用 $CI_COMMIT_REF_SLUG 而非 $CI_JOB_NAME + $CI_COMMIT_SHA)、或缓存路径没覆盖 vendor/ 和 ~/.composer/cache/。
正确配置 composer 缓存的三个关键路径
必须同时缓存以下三处,缺一不可:
-
vendor/:项目依赖目录,最直接影响composer install是否跳过安装 -
~/.composer/cache/:Composer 自身的包缓存(含 zip 包、dist 文件),决定下载阶段是否复用 -
~/.composer/files/:部分版本(如 2.2+)会把已安装包的 hash 校验文件放这里,漏掉会导致重复校验
GitLab CI 的 cache: 配置需显式列出这三项,不能只写 vendor/。
推荐的 .gitlab-ci.yml 片段(兼容 Composer 2.x)
cache:
key: ${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}
paths:
- vendor/
- ~/.composer/cache/
- ~/.composer/files/
before_script:
- export COMPOSER_CACHE_DIR="${HOME}/.composer/cache"
- export COMPOSER_HOME="${HOME}/.composer"
- composer self-update --2
test: script:
- composer install --no-interaction --prefer-dist --optimize-autoloader
说明:
-
key使用${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}可兼顾分支隔离与 job 复用,比单纯用$CI_COMMIT_SHA更实用 -
--prefer-dist强制走压缩包安装,避免 git clone(CI 环境通常无 git 凭据) -
--optimize-autoloader必须加,否则缓存的vendor/autoload.php可能不生效 - 不要用
composer install --no-scripts,除非你确认项目无 post-install-cmd 脚本(如生成配置、清理缓存等)
当缓存仍不命中时,快速诊断方法
在
script:中临时加入检查命令:script: - ls -la ~/.composer/cache/files/ - composer show --no-dev | head -5 - echo "Cache key: ${CI_JOB_NAME}-${CI_COMMIT_REF_SLUG}"观察输出:
- 如果
~/.composer/cache/files/下为空,说明缓存根本没恢复成功,检查cache:paths是否拼写错误(比如写成~/.composer/cache少了末尾斜杠) - 如果
composer show输出大量 “Installing…” 行,说明vendor/没被缓存命中,大概率是cache:key变了或上一次构建失败导致缓存被丢弃 - GitLab UI 的 “Job log” 里搜索
Cached paths和Restored cache行,确认实际恢复了哪些路径
缓存逻辑本身简单,但路径、key、权限三者只要一个对不上,就退化成全量下载。CI 环境下别信“应该会自动缓存”,每个路径都得亲手验证。
-










