composer install 在无网络服务器上报错,因默认需访问 packagist.org、调用 git/curl、执行钩子脚本;离线运行须提前在有网环境安装并打包 vendor 和 composer.lock,目标机解压后执行 composer install --no-interaction --no-scripts 并补 dump-autoload。

composer install 为什么在没网络的服务器上直接报错?
因为默认行为会去 packagist.org 拉包,还会调用 git clone 或 curl 下 zip 包,甚至执行 composer validate 和 composer update 的钩子逻辑。没网络 + 没 root 权限 = 连 composer.phar 自身都可能跑不起来——比如它试图写 /tmp 但被限制,或找不到系统级 openssl 扩展。
怎么让 composer install 完全离线运行?
核心是「把所有依赖提前下好、冻结、打包、带过去」,不是靠临时改配置蒙混过关。关键动作有三步:
- 在有网+有权限的机器上,用
composer install --no-dev --prefer-dist --optimize-autoloader装一遍,确保vendor/干净可复现 - 执行
composer archive --format=zip --dir=./dist your-project-name(或直接zip -r vendor.zip vendor/),连vendor/和composer.lock一起打进去 - 目标服务器上,只要 PHP 可执行、
ext-zip和ext-json已启用,就解压vendor.zip到项目根目录,再跑composer install --no-interaction --no-scripts
注意:--no-scripts 很关键——很多私有包的 post-install-cmd 会尝试调外部 API 或写系统路径,没 root 权限时大概率崩。
vendor 目录带过去后,autoload 还失效?
常见原因是 autoloader 没重生成,或用了 dev-only 的类。必须在目标机上补这一步:
- 删掉
vendor/autoload.php和vendor/composer/autoload_*.php(别手抖删整个vendor/) - 运行
php -d extension=zip.so composer.phar dump-autoload --optimize(确保composer.phar是静态编译版,不依赖系统curl或openssl) - 如果提示
Class not found,检查composer.json里有没有"autoload-dev"误被引入,或者psr-4映射路径写死了本地绝对路径(比如/home/user/project/src)
为什么不能直接 rsync vendor/ 过去就完事?
因为 vendor/ 里有些包含平台相关二进制(如 hirak/prestissimo 的 phar stub)、或硬编码了构建时的 realpath(),还有些包的 install-path 在 composer.lock 里记录的是源路径。最稳妥的方式是:只传 composer.lock + composer.json + 离线镜像包(packages.json + .zip 文件),再用 composer install --repository-url=file:///path/to/mirror 指向本地文件系统。
不过对无 root 服务器来说,这反而更麻烦——你得确保 file:// 协议能读取那个路径,且 PHP 没禁用 allow_url_fopen。所以多数人最后还是选「打包 vendor + lock 文件」,只是多加一步 dump-autoload 来兜底。
真正卡住的点往往不是 composer 本身,而是某个包的 install 脚本偷偷 exec 了 npm install 或调了 which python3——这种没法离线,得提前 patch 掉。










