先说一个很多人踩过的坑:Composer 镜像一宕机,composer install 直接报错中断,连个喘息的机会都不给。这不是 bug,而是 Composer 设计上就没打算自动帮你 fallback 到备用源——它把 repositories 数组当元数据合并表来用,根本不是请求路由表。一旦第一个镜像(比如阿里云)返回超时、502 或 DNS 失败,流程就立刻掐断,第二个源连看都不看一眼。你听过的“写多个源就能容灾”,是典型的误解。

镜像宕机时 composer install 直接报错,不是 bug 是设计
Composer 的容错策略其实很“死板”:它把 repositories 数组当作元数据合并表,而不是请求路由表。一旦第一个镜像(比如阿里云)返回超时、502 或 DNS 失败,composer install 就立刻中断,连尝试第二个源的机会都没有。你看到的“写多个源就能容灾”,是常见误解。
真容灾必须三步原子执行:探测 + 切换 + 清缓存
靠手动改配置或等重试没用,得用脚本把下面三件事串起来,缺一不可:
- 用
curl -I -s -o /dev/null -w "%{http_code}" https://mirrors.aliyun.com/composer/packages.json检查镜像根路径是否返回200;非 200 就判定失效 - 执行
composer config repositories.packagist composer https://mirrors.tencent.com/composer/(项目级,不加-g),动态覆盖生效源 - 必须
rm -rf ~/.composer/cache/repo/https---mirrors.aliyun.com-composer——composer clear-cache不管用,它只清 ZIP 包,不删元数据缓存目录
切源后 signature 验证可能失效,安全风险常被忽略
直接用 composer config -g repo.packagist composer https://xxx/ 会跳过签名校验,镜像若缓存污染或未同步 signature 字段,就可能拉下篡改包。正确做法是:
- 启用签名验证:
composer config -g security.signature true - 用
repos.packagist键名(不是repo.packagist),并设 type 为composer:composer config -g repos.packagist.type composer - 再设 URL:
composer config -g repos.packagist.url https://mirrors.aliyun.com/composer/ - 验证:
composer diagnose输出里必须同时有secure-http: OK和signature verification: OK
最稳的保底手段其实是离线 install,不是换镜像
只要 composer.lock 存在且完整,composer install 就完全不发网络请求——它只从 ~/.composer/cache/files/ 读 ZIP、校验哈希、解压。这才是宕机时真正可靠的路径:
composer.lock必须提交进 Git,不能出现在.gitignore里- CI 流水线要复用
~/.composer/cache目录(如 GitHub Actions 的actions/cache) - 本地开发完成一次
composer install后,缓存目录里已有全部依赖;下次宕机,rm -rf vendor && composer install仍能成功
镜像配置只是加速手段,不是容灾本身。很多人配了阿里云就以为万事大吉,却没开 signature、没固化 lock、也没在 CI 中复用缓存——结果镜像一延迟,构建照样失败。