正确离线安装composer依赖的核心是预下载并复用本地缓存:先联网执行composer install确保所有包进入composer_home/cache,再将cache目录复制到离线机,设置composer_cache_dir环境变量后运行composer install --no-interaction --prefer-dist。

composer install 时加 --no-install 不行,得用 composer install --no-scripts --no-plugins 配合缓存机制
离线预下载的核心不是“跳过安装”,而是让 Composer 把所有包的 zip/tar 包提前拉下来并存进本地 cache,后续离线时再从 cache 解压。默认 composer install 只在需要时才下载,且会执行脚本和插件——这些在离线环境大概率失败,反而污染状态。
正确做法是:先在有网机器上完整跑一次 composer install(确保 vendor/ 和 composer.lock 齐全),让所有包进 cache;再把整个 COMPOSER_HOME/cache/ 目录打包带走。cache 路径可通过 composer config --global cache-dir 查看。
-
--no-scripts和--no-plugins不是为加速,是防止某些包的 post-install-cmd 在无网时卡死或报错 - 别依赖
composer archive——它只打当前项目,不包含依赖包的源码压缩包 - 如果项目用了私有 repo,记得提前用
composer config repositories.xxx注册好,否则 cache 里不会存那些包
离线环境下必须设置 COMPOSER_CACHE_DIR 指向预下载的 cache 目录
Composer 默认 cache 路径是用户主目录下的隐藏文件夹,离线机器上这个路径通常为空。即使你拷了 cache 过来,不显式告诉 Composer 去哪找,它还是会尝试联网下载。
执行前先设环境变量:export COMPOSER_CACHE_DIR=/path/to/your/cachedir(Linux/macOS)或 set COMPOSER_CACHE_DIR=C:\path\to\cachedir(Windows)。然后运行 composer install --no-interaction --prefer-dist。
-
--prefer-dist强制走 zip 包安装(而非 git clone),这是 cache 生效的前提 - 如果 lock 文件里某包只有
source类型(比如开发中手动改过repositories),cache 里没 dist 包,就会失败——这种情况得提前检查composer show vendor/package确认 type 是 dist - 不同 Composer 版本 cache 格式不完全兼容,离线机的 Composer 版本最好和预下载机一致(
composer --version对齐)
验证 cache 是否真正生效:看日志里有没有 Downloading ... 或 Writing into cache
执行 composer install -v(verbose 模式)是最直接的验证方式。正常离线安装时,你应该看到类似 Using version ^2.4 for monolog/monolog 和 Installing monolog/monolog (2.4.0): Loading from cache 的输出。一旦出现 Downloading https://.../monolog/monolog/...,说明某包没进 cache 或路径没对上。
- 注意区分 “Loading from cache”(成功)和 “Cache is not hit”(失败)——后者常见于 hash 不匹配,通常是 lock 文件被改过但没重生成
- 如果某个包反复提示未命中 cache,用
ls -la $COMPOSER_CACHE_DIR/files/vendor/package/看对应 hash 目录是否存在,不存在就说明预下载阶段根本没拉下来 - 私有包若用的是
package类型定义(非 VCS),它的 dist URL 必须可公开访问或已提前下载到 cache,否则离线时无法 fallback
docker 构建中离线安装要额外处理 vendor 目录权限和 cache 挂载
在 CI 或 Dockerfile 里做离线构建时,光拷 cache 不够。因为 vendor/ 是写入目标,而构建镜像时 user 权限、layer 缓存、workdir 路径都可能干扰 cache 查找逻辑。
- Dockerfile 中建议分两层:先
COPY composer.json composer.lock .,再RUN COMPOSER_CACHE_DIR=/tmp/composer-cache composer install --no-interaction --prefer-dist,最后COPY --from=cache-builder /tmp/composer-cache /root/.composer/cache - 避免在
vendor/所在目录执行composer install后再rm -rf vendor——这会清掉刚解压的文件,但 cache 本身不受影响;真正危险的是误删$COMPOSER_CACHE_DIR - Alpine 镜像里注意
php-zip扩展必须安装,否则--prefer-dist会静默 fallback 到 source,导致离线失败










