无公网环境不能直接配置阿里云镜像,因命令依赖网络且dist url仍指向境外;必须用satis构建含zip包的完整离线镜像,严格配置archive.prefix-url、repositories结构及执行用户权限。

无公网环境 ≠ 能直接用阿里云镜像
不能执行 composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,因为该命令依赖网络写入远程元数据入口,而无公网时连不到阿里云域名,会静默失败或报 Could not resolve host。国内公开镜像(阿里、腾讯、华为)只缓存 packages.json 和 provider 文件,不托管 ZIP 包;更关键的是,它们的 dist URL 仍指向 GitHub、GitLab 等境外地址——这些在无公网环境下根本不可达。
必须用 Satis 构建完整离线镜像
真正可行的方案是用 satis 在有网机器上抓取全部依赖(含 ZIP 包),生成静态文件,再拷贝到内网服务器。这不是“换源”,而是重建整个包生态:
-
satis.json中必须显式列出所有需要的包(或设"require-all": false),避免require-all: true导致首构建超 40GB、内存溢出 -
archive.prefix-url必须填内网可访问的 HTTP 地址(如http://pkgs.internal),且末尾带斜杠 —— 少斜杠会导致 ZIP 路径拼错,返回 404 -
build后输出目录需由 Nginx/Apache 托管,root必须精确指向output-dir,并配置types { application/json json; },否则 Composer 拒收packages.json - 验证 ZIP 是否真能直连:手动访问类似
http://pkgs.internal/dist/monolog/monolog/2.10.0/monolog-2.10.0.zip,HTTP 200 才算通
项目级配置必须严格匹配私有源结构
离线项目里的 composer.json 不能只改 repo.packagist,必须完整定义私有仓库:
-
repositories数组首位必须是你的内网源,且"type": "composer"、"url": "http://pkgs.internal/"(注意末尾斜杠) - 必须加
"packagist.org": false,放在repositories数组外层,不是嵌套在某个仓库对象里 - 不能留空
repositories字段,哪怕只写[],也会让 Composer 忽略全局配置、跳过你刚配的私有源 - 运行
composer show monolog/monolog --verbose,确认dist.url指向的是内网地址,而非原始 GitHub 链接
CI 或宝塔等多用户场景要切换执行用户
构建好的镜像部署到内网服务器后,实际执行 composer install 的用户可能不是你本人:
- 宝塔面板默认以
www用户运行 PHP CLI,需先sudo -u www composer config -g repo.packagist composer http://pkgs.internal/ - Docker 容器中若用非 root 用户,
~/.composer/config.json路径归属必须匹配该用户,否则配置不加载 - GitHub Actions 等 CI 环境不会读全局配置,必须在脚本开头插入
composer config repo.packagist composer http://pkgs.internal/ - 每次换环境都得重新验证:
composer config -g repo.packagist输出是否为内网地址,而不是空或https://packagist.org
Loading composer repositories 或 Could not find package —— 而错误日志里往往不提示具体哪一环断了。











