根本原因是磁盘iops瓶颈,尤其在docker挂载卷、vm共享文件夹或低速ssd上,小文件密集操作被系统限速;需禁用vendor挂载、改用命名卷,迁移cache-dir和sys_temp_dir至高速介质,并降低并发、配置多镜像、关闭非必要缓存。

为什么镜像同步卡在“Extracting archive”不是网络慢
根本原因是 Composer 在解压 ZIP 包时触发了磁盘 IOPS 瓶颈,尤其在 macOS/Windows 的 Docker 挂载卷、VM 共享文件夹或低速 SSD 上——stat()、open()、read() 这类小文件密集操作被系统限速,导致单个包解压耗时飙升,Downloading 看似卡住,实则是写入排队堆积。报错里出现 No space left on device 却 df -h 显示空间充足,大概率是 df -i 显示 inode 100%,根源仍是 IOPS 不足引发的临时文件残留和缓存目录膨胀。
禁用 vendor 挂载 + 改用命名卷(Docker 场景必做)
把 vendor/ 目录挂载进容器是最常见陷阱:宿主机 ↔ 容器间所有文件操作都经由文件系统桥接层,macOS 的 APFS 和 Windows 的 WSL2 都会显著放大 IOPS 延迟。一旦并发下载开始,几百个 ZIP 解压请求挤在同一个挂载点上,立刻触发队列阻塞。
- 删掉
docker-compose.yml里类似- ./vendor:/app/vendor的挂载项 - 改用命名卷:在
services下加volumes: - composer-vendor:/app/vendor,并在volumes顶层声明它 - 确保
composer install在容器内执行,而不是宿主机跑完再拷贝进去 - 若需复用已装好的 vendor,用
rsync -av --delete vendor/ container:/app/vendor替代实时挂载
把 cache-dir 和 sys_temp_dir 都挪到高速介质
Composer 默认缓存路径(~/.composer/cache)和 PHP 临时目录(sys_get_temp_dir())若落在机械硬盘、网络存储或 Docker overlay2 上,IOPS 限制会直接拖垮整个流程。两者必须同时迁移,只动一个效果有限。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 查当前缓存位置:
composer config -g cache-dir - 迁移到 SSD:
composer config -g cache-dir /mnt/ssd/composer-cache - 查 PHP 临时目录:
php -r "echo sys_get_temp_dir();" - Linux/macOS 启动时指定:
TMPDIR="/mnt/ssd/tmp" php -d sys_temp_dir="/mnt/ssd/tmp" composer install - Windows PowerShell:
$env:TMP="D:\temp"; $env:TEMP="D:\temp"; php "-d" "sys_temp_dir=D:\temp" composer install - 目标目录需存在且可写:
mkdir -p /mnt/ssd/tmp && chmod 1777 /mnt/ssd/tmp
降并发 + 多镜像 + 关缓存,三者缺一不可
高并发下载(默认 5–10)会瞬间打满镜像站 QPS 限额,导致大量连接超时并堆积在磁盘写入队列——这不是网络带宽问题,而是请求被限流后,Composer 还在等每个失败连接超时(默认 300 秒),造成 IOPS 持续空转。
- 全局设低并发:
composer config -g repos.packagist.org.concurrent-downloads 2 - 配至少 3 个国内镜像,每个带
"canonical": false,例如阿里云、腾讯云、华为云 - 关非必要缓存:
composer config -g cache-files-ttl 0(不缓存 ZIP)、composer config -g cache.source false(不缓存 Git 源码) - 清旧缓存:
composer clear-cache,否则配置不生效 - 验证:
composer config -g | grep concurrent应输出"concurrent-downloads": 2
真正容易被忽略的是临时目录和缓存目录的物理位置——它们可能分属不同挂载点,一个在 SSD、一个还在 overlay2,IOPS 瓶颈就藏在这里。别只盯着 cache-dir,sys_get_temp_dir() 同样关键,且更隐蔽。










