私有镜像源是代理或只读缓存服务,非迁移包;它按需拉取并缓存开源包,无需手动上传;常见方案为packagist-mirror、Satis和Private Packagist;配置后需禁用默认源并清空本地缓存。

私有镜像源不是“迁移包”,而是代理或缓存服务
Composer 本身不提供“把开源包迁移到私有镜像”的功能——你没法用一条命令把 monolog/monolog 或 laravel/framework “上传”到自己搭的服务器上。所谓私有镜像,本质是 代理(proxy) 或 只读缓存(mirror) 服务:它在首次请求某个包时,从 packagist.org 或 GitHub 拉取元数据和 ZIP 包,存下来,后续请求直接返回本地副本。
这意味着:你不需要、也不能手动“迁移”任何开源包;只要配置好私有服务,并让 Composer 指向它,它就会自动按需拉取并缓存。
- 常见实现方案只有三类:
packagist-mirror(轻量 CLI 工具)、Satis(静态生成)、Private Packagist(商业托管) -
composer config命令只能指向已有镜像源(如阿里云),不能“搭建”私有镜像——那是独立服务的事 - 如果你只是想加速公开包,别折腾私有镜像;直接切阿里云/腾讯云即可
用 packagist-mirror 搭建最小可行私有镜像
packagist-mirror 是目前最轻量、维护最活跃的开源方案,适合中小团队自建。它不生成静态文件,而是运行一个 HTTP 服务,实时代理 + 缓存请求。
实操步骤:
- 确保服务器有 PHP 8.0+、Git、cURL、Redis(可选,用于锁和并发控制)
- 执行:
composer create-project composer/packagist-mirror(注意:这不是composer install,必须用create-project) - 复制
config.example.php为config.php,改关键项:'upstream' => 'https://packagist.org'(保持默认即可)'cache_dir' => '/var/cache/packagist-mirror'(确保目录可写) - 用
php -S localhost:8080 router.php启动服务(仅开发测试);生产环境必须用 Nginx/Apache 反代,并启用 HTTPS
启动后访问 http://your-server:8080/packages.json,应返回合法 JSON——说明镜像服务已就绪。
让 Composer 项目真正走你的私有镜像
服务跑起来 ≠ Composer 就会用它。必须显式配置,且注意优先级陷阱:
- 全局配置(推荐 CI/CD 统一管理):
composer config -g repositories.packagist.org '{"type": "composer", "url": "https://your-mirror.example.com/"}'(注意:Composer 2.2+ 推荐用repositories.packagist.org,不是repo.packagist) - 项目级配置(更稳妥,避免污染全局):
cd your-project && composer config repo.packagist composer https://your-mirror.example.com/ - 必须加
"packagist.org": false屏蔽默认源,否则未缓存的包仍会 fallback 到官方源——在项目composer.json的repositories数组开头插入该项 - 验证方式不是看速度:运行
composer update -vvv | grep "GET ",确认日志中所有packages.json和dist请求都命中你的域名
同步延迟、私有包共存与 fallback 策略
私有镜像不是魔法盒,它受上游限制,也影响协作流程:
- 新发布的包(尤其是
dev-main或刚tag的版本)可能尚未被镜像拉取——此时请求会 404。不要立刻认为服务挂了,先查上游是否真已发布 - 若同时使用私有 VCS 包(如公司内部 GitLab 仓库),
repositories必须并列声明:packagist.org镜像项 +vcs项,且vcs项不能放在packagist.org前面,否则 Composer 可能跳过镜像直连 - 腾讯云镜像默认开启 fallback(找不到就试官方源),但私有镜像默认不 fallback——你得自己在 Nginx 层做 404 重定向,或改
packagist-mirror的config.php中的'fallback' => true - 最关键的一步常被跳过:
composer clear-cache。旧的packages.json元数据还存在本地,即使镜像已生效,install仍可能连错源
真正难的不是搭服务,而是让所有人(包括 CI 脚本、新同事、Docker 构建)都一致地指向它,且理解它不解决“包不存在”问题——只解决“下载慢”问题。











