直接配 cache-dir 不等于本地缓存网关,因其仅为单机路径、不自动同步且并发写入易冲突损坏;真正降低公网带宽需部署 http 代理型本地缓存网关(如 nginx+lua 或 satis),拦截并缓存 packagist.org 的 dist 和 repo 请求,严格复现响应头与缓存键。

为什么直接配 cache-dir 不等于本地缓存网关
很多人以为把 cache-dir 指向一个共享目录(比如 NFS 或局域网 SMB 共享),就能让团队共用缓存、省带宽。实际不是——Composer 默认只读写本地路径,cache-dir 是单机配置,不自动同步、不协调并发写入,多人同时 install 会触发文件锁冲突或覆盖,甚至损坏 repo/ 下的 packages.json 缓存结构。
真正能降低出公网带宽的,是「本地缓存网关」:它本质是一个 HTTP 代理服务,拦截所有对 packagist.org 的 GET 请求(如 /p2/monolog/monolog.json、/dist/monolog/monolog/xxx.zip),命中则返回本地缓存副本,未命中才透传并落盘。这不是 Composer 自身功能,而是靠反向代理(如 Nginx + Lua 或 Satis/SatisMirror)实现。
- 必须监听所有 dist 和 repo 请求路径,不能只代理 ZIP 文件——元数据(
packages.json)缺失会导致版本解析失败 - HTTP 响应头需严格复现原始服务的
ETag、Last-Modified、Cache-Control,否则 Composer 会重复请求 - 缓存键必须包含完整 URL 路径 + query 参数(如
?h=abc123),否则不同 commit 的包可能混用
用 Satis 搭建最小可行本地缓存网关
Satis 是官方推荐的私有包仓库工具,它能抓取 Packagist 元数据并生成静态 JSON + ZIP 镜像,配合 Web 服务器即可充当缓存网关。它不转发请求,而是提前固化资源,规避了代理层的并发和一致性难题。
关键操作步骤:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在内网服务器上安装 Satis:
composer create-project composer/satis --stability=stable - 编写
satis.json,显式列出要镜像的包(避免全量同步拖垮磁盘):{ "name": "internal-mirror", "repositories": [ { "type": "composer", "url": "https://packagist.org" } ], "require-all": false, "require-dependencies": true, "output-dir": "/var/www/satis" } - 运行构建:
php bin/satis build satis.json /var/www/satis—— 这会下载所有指定包的 ZIP 和元数据,并生成packages.json索引 - Nginx 配置 root 指向
/var/www/satis,确保能直接访问https://satis.internal/p2/monolog/monolog.json
注意:Satis 构建过程仍需联网,但只需执行一次;后续团队所有 composer install 只连内网地址,完全不出公网。
项目里怎么安全切换到本地网关
切勿直接修改全局 composer config --global repo.packagist.org——这会影响所有项目,且无法回滚。正确做法是在每个项目 composer.json 中临时覆盖源:
- 添加
repositories数组,把packagist.org设为禁用,并指向内网地址:"repositories": [ { "packagist.org": false }, { "type": "composer", "url": "https://satis.internal" } ] - 必须保留
"packagist.org": false,否则 Composer 会在 fallback 时重连公网(尤其当包在本地镜像中不存在时) - 首次切换后,运行
composer update --lock重新生成composer.lock,确保所有 dist URL 指向内网路径 - CI 流水线中,需确保
COMPOSER_HOME不干扰该配置——项目级repositories优先级高于全局配置
常见故障:明明配了网关却还在拉公网包
最常发生的原因不是配置错,而是缓存未命中后 Composer 自动 fallback 到 packagist.org。现象是 composer install 日志里出现 Downloading https://packagist.org/p2/... 或 Downloading https://files.phpcomposer.com/...。
- 检查
composer.json是否漏写了"packagist.org": false—— 这是硬性开关,缺了就 fallback - 确认 Satis 构建时是否包含目标包:访问
https://satis.internal/p2/vendor/name.json,返回 404 就说明没镜像到 - 查看
composer.lock中对应包的dist.url字段,必须是内网地址(如https://satis.internal/dists/xxx.zip),不是https://api.github.com/...或https://files.phpcomposer.com/... - Windows 下若用 WSL 访问内网 Satis,注意防火墙是否放行端口,且
https://satis.internal能被curl -I正常响应
真正起效后,strace -e trace=connect php composer.phar install 2>&1 | grep -E ':(80|443)' 应只看到连接内网 IP,绝无境外地址。










