离线安装 composer 依赖必须使用 satis 构建本地镜像,而非仅复制 vendor 或依赖 composer.lock;需在有网环境生成完整 packages.json 和 zip 包,内网通过 http 服务提供,并在项目 composer.json 中配置本地仓库地址且禁用 packagist.org。

离线安装 Composer 依赖,靠的是提前固化资源,不是“跳过联网”
没有网络时 composer install 能成功,前提是它根本不需要联网——这只有在 composer.lock 存在、且所有包的 ZIP 文件或源码已本地可得时才成立。直接把 vendor 目录打包复制到另一台机器,90% 情况下会失败,因为 autoload 映射缺失、扩展依赖未满足、或路径硬编码导致类找不到。
用 Satis 构建完整离线镜像(推荐长期方案)
Satis 是 Composer 官方维护的静态仓库生成工具,它不运行服务、不依赖数据库,只输出 packages.json 和一堆 ZIP 包,Nginx 或 python3 -m http.server 就能跑起来。关键不是“下载缓存”,而是“构建一个功能等价的 packagist.org 替身”。
- 在有网机器上执行:
composer create-project composer/satis --stability=stable - 写好
satis.json,明确列出项目实际用到的所有顶层包(别信"require-all": true,它会拉下几十 GB 的无用包) - 运行:
php bin/satis build satis.json web/—— 这一步会递归解析依赖、下载 dist ZIP、生成 autoload 信息,并全部放进web/目录 - 把整个
web/目录拷进内网机器,用python3 -m http.server 8000启动,访问http://127.0.0.1:8000/packages.json能打开就算成功
项目里怎么告诉 Composer:“别上网,就认这个本地地址”
光有镜像没用,项目必须主动切换源。最稳妥的方式是改 composer.json,而不是全局 config——后者会影响所有项目,且容易被忽略。
- 在
composer.json中添加"repositories"块,把本地镜像放第一位:
"repositories": [
{ "type": "composer", "url": "http://127.0.0.1:8000" }
],
"packagist.org": false
composer clear-cache,否则 Composer 可能仍从旧缓存读取元数据composer install --no-interaction,它会从 http://127.0.0.1:8000/packages.json 拉清单,再从同域名下的 dist/xxx.zip 下载安装私有包、Git 依赖、dev 包这些怎么处理?
如果项目用了公司内网 GitLab 的私有库,或 require-dev 里的测试工具(如 phpunit/phpunit),Satis 默认不会拉它们——除非你显式写进 satis.json 的 "require" 里,或启用 "require-dependencies": true(但要小心 dev 包污染生产镜像)。
- 对私有 Git 库:改用
"type": "package"+"dist"方式,把代码打成 ZIP 放进内网 HTTP 可访问路径,然后在composer.json里声明 URL - 对 dev 包:若离线环境也要跑测试,
satis.json中需保留"skip-dev": false,并在archive配置里确保dist目录包含它们 - 最容易漏的是“间接依赖”:比如你 require
guzzlehttp/guzzle,但它内部 requirepsr/http-client,而你没在satis.json里列出来——Satis 就不会下载,安装时就会报错“package not found”
composer.lock + vendor 复制就能离线,结果 autoload 错、扩展缺、私有包 404。Satis 镜像不是可选项,是离线场景的基础设施——它强制你把整个依赖树显式声明、提前验证、物理固化。










