直接挂载 ~/.composer-cache 并配对国内镜像源,create-project 在 CI 容器里能从 5+ 分钟压到 30 秒内;核心是镜像源、缓存路径、composer.lock 三者对齐,缺一不可。

直接挂载 ~/.composer-cache 并配对国内镜像源,create-project 在 CI 容器里能从 5+ 分钟压到 30 秒内 —— 不是调参玄学,而是缓存路径、镜像 URL、lock 文件三者必须对齐。
为什么 create-project 在容器里卡在 “Installing dependencies”
这不是网络慢,是它在反复请求 packagist.org 的元数据(比如 packages.json、provider-laravel~10.0.json),而默认直连成功率极低。容器里没配镜像源,等于裸奔;没挂缓存卷,每次都要重下 ZIP 包、重解压、重生成 autoload。
-
create-project本质是先git clone或下载模板包,再执行一次完整的composer install - 它不读宿主机的
~/.composer/config.json,容器内必须显式配置镜像源 - 若
composer.lock里 dist URL 还是https://repo.packagist.org,哪怕全局配了阿里云镜像,也会 fallback 校验失败
必须执行的三步初始化(CI 脚本开头)
这三步缺一不可,顺序不能乱:
-
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/(注意末尾/) -
composer config -g cache-files-dir ~/.composer-cache/files(路径必须和挂载点一致) -
composer clear-cache(换源后不清缓存,旧包 hash 可能校验失败)
验证是否生效:composer config -g repo.packagist 输出应为完整 JSON 对象,composer show packagist/support -vvv 日志中应出现 GET https://mirrors.aliyun.com/composer/。
docker run 命令中挂载缓存卷的关键写法
只挂 vendor/ 或只挂 composer.json 没用 —— create-project 的缓存主体是 ~/.composer-cache/files/,且必须让容器进程有写权限:
- Linux/macOS:用
--user $(id -u):$(id -g)+-v ~/.composer-cache:/tmp/cache -e COMPOSER_CACHE_DIR=/tmp/cache - Windows WSL:改用
--user 1001:1001,并确保~/.composer-cache目录存在且可写 - 别用
--rm -v $(pwd):/app就完事,漏掉缓存卷等于没做
完整示例:
docker run --rm -v $(pwd):/app -v ~/.composer-cache:/tmp/cache -e COMPOSER_CACHE_DIR=/tmp/cache --user $(id -u):$(id -g) -w /app composer create-project laravel/laravel . --prefer-dist --no-dev --optimize-autoloader --no-interaction
CI 中缓存 key 失效最常踩的坑
缓存明明挂了却总不命中,八成是 key 设错了:
- GitHub Actions:key 必须包含
hashFiles('**/composer.lock'),否则 lock 文件一变,缓存就废 - GitLab CI:别用
${CI_COMMIT_TAG}当 key,未打 tag 时 fallback 到默认值,导致跨分支缓存污染 - 私有包场景:若项目依赖私有 GitLab 包,
COMPOSER_AUTH必须提前注入 CI 变量,否则认证失败会强制重拉,缓存形同虚设
真正要缓存的只有两样:~/.composer-cache(环境无关)和 composer.lock(决定依赖树唯一性)。vendor/ 绝对不要进 CI 缓存 —— PHP 版本、扩展差异会导致 autoload 错误,比慢更致命。


















