cache-read-only设为true后缓存路径仍需可读且含有效文件;它跳过写操作但依赖读取,若路径不可读、为空或挂载只读,Composer将静默回退到重新下载。

cache-read-only 设为 true 后,缓存路径还必须可写?
不是的。cache-read-only 确实会让 Composer 完全跳过写缓存的操作,但它**不解除对缓存目录的读取依赖**——也就是说,你仍需提供一个已存在、可读、且包含有效缓存文件的路径。如果该路径根本不可读(比如权限拒绝、挂载为只读、或压根没缓存内容),Composer 会静默 fallback 到默认行为:重新下载所有包,就像没缓存一样。
为什么设了 cache-read-only 还报 Permission denied?
常见于 Docker 或 CI 场景,错误不在 cache-read-only 本身,而在缓存目录的挂载方式或所有权:
- 挂载时用了
:ro(只读)标志,但 Composer 需要读取files/子目录下的 zip 包,而只读挂载会阻止 stat() 或 open() 操作(尤其在某些内核或 overlayfs 下) - 目录属主是
root,但运行 composer 的用户(如www-data)无权进入该目录(ls -ld /path/to/cache第三列不是当前用户) -
cache-files-dir指向的是父目录(如/cache),但实际生效路径必须是/cache/files;只配父目录会导致 Composer 认为“缓存不可用”,直接绕过
只读场景下真正有效的配置组合
要让 cache-read-only 在只读文件系统上稳定工作,必须同时满足三个条件:
- 设置
cache-read-only:运行composer config --global cache-read-only true(或写入~/.composer/config.json) - 显式指定
cache-files-dir:必须是绝对路径 +/files后缀,例如composer config --global cache-files-dir /mnt/shared-cache/files - 确保该
/files目录存在、可读、且已有历史缓存内容(不能空);挂载时避免:ro,改用:rw,z(Podman)或:rw,delegated(Docker for Mac)
验证是否真走缓存:执行 composer install 后,检查 composer diag 输出中的 Cache directory 和 Cache files directory 是否一致指向你配的路径,并确认 Cache hit rate > 0。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
CI 中临时启用只读缓存的最简命令
不需要改全局 config,一条命令即可启动只读模式:
COMPOSER_CACHE_DIR="/tmp/composer-cache" \ COMPOSER_CACHE_READ_ONLY=1 \ composer install
注意:COMPOSER_CACHE_READ_ONLY=1 是环境变量形式,优先级高于 config 文件;它等价于 cache-read-only=true,但更易在脚本中动态控制。只要 /tmp/composer-cache/files 已预填充且可读,Composer 就不会尝试写任何东西——这才是“只读文件系统”下真正安全的用法。
最容易被忽略的一点:即使开了 cache-read-only,如果 cache-files-dir 下没有对应 PHP 版本 + lock 文件哈希的缓存子目录,Composer 依然会重下。所以只读缓存不是“开关”,而是“快照复用”——它只认完全匹配的缓存块。

















