不能直接挂载vendor到overlayfs upperdir,因其破坏composer缓存语义:vendor非原子写入,overlayfs的cow机制易致inode不一致、元数据丢失、权限错乱;应overlay只读的$home/.composer/cache/files目录,配合lowerdir预热与upperdir租户隔离。

为什么不能直接挂载 vendor 到 OverlayFS upperdir
直接把 vendor/ 目录挂进 OverlayFS 的 upperdir 会破坏 Composer 自身的缓存语义:Composer 安装时依赖文件权限、mtime、符号链接完整性,而 OverlayFS 在写时拷贝(COW)过程中可能触发不一致的 inode 复制或元数据丢失。更关键的是,vendor/ 不是原子写入单元——一次 composer install 可能同时创建数百个目录和文件,OverlayFS 的并发写入日志和 workdir 冲突会导致部分文件缺失或权限错乱,最终表现为 Class not found 或 require(): failed to open stream。
真正该 overlay 的是 $HOME/.composer/cache/files
Composer 的下载包缓存(~/.composer/cache/files)才是安全叠加的目标:它只包含只读的 zip/tar 包、按 hash 命名的文件,无执行权限要求,无目录树深度依赖。OverlayFS 的 lowerdir 可固定挂载一个预热好的全局缓存镜像(如 /var/lib/composer-cache-ro),upperdir 指向每个租户独立的写层(如 /var/lib/jenkins/workspace/${JOB_NAME}/composer-cache-rw),这样既能复用 90%+ 的 dist 包,又避免跨租户污染。
-
lowerdir必须是只读挂载(mount -o ro,bind),否则 OverlayFS 拒绝启动 -
workdir不能与upperdir共享父目录,否则出现overlayfs: workdir and upperdir must be on the same filesystem - 租户构建前需确保
upperdir为空或已清理,否则旧缓存残留会干扰新 lock 文件解析
Jenkins Pipeline 中如何安全启用 overlay 缓存
不要在 sh 步骤里手动 mount —— Jenkins agent 生命周期短,挂载点易失效且权限难管控。正确做法是在 agent 启动阶段由 systemd 或 Docker entrypoint 预置:
PyCharm 2026.2.0.1 Linux版提供 JetBrains 官方 2026.2.0.1 版本安装包,适合需要指定 PyCharm 版本进行 Python 项目开发、运行和调试的用户。
- 在 agent 主机上创建统一 lower 层:
sudo rsync -a /prewarmed/composer-cache/ /var/lib/composer-cache-ro/,然后sudo chmod -R 555 /var/lib/composer-cache-ro - Docker agent 启动参数加:
--volume /var/lib/composer-cache-ro:/home/jenkins/.composer/cache/files:ro --volume /tmp/composer-cache-${JOB_NAME}:/home/jenkins/.composer/cache/upper:rw - Pipeline 中只需保证
COMPOSER_CACHE_DIR=/home/jenkins/.composer/cache,无需额外命令,composer install --prefer-dist自动命中 overlay 后的缓存路径
多租户场景下 cache key 为何仍要绑定 composer.lock 哈希
OverlayFS 提供了物理层复用,但 Composer 逻辑层仍需感知 lock 变更:即使 dist 包已存在,若 composer.lock 新增了 require-dev 依赖或切换了 VCS 分支,composer install 仍会触发部分重下载和 autoload 重建。此时仅靠 overlay 不足以跳过全部操作,必须配合 cache key 粒度控制:
- 使用
cache(key: "composer-${sh(script: 'sha256sum composer.lock | cut -d\" \" -f1', returnStdout: true).trim()}'", paths: ['.composer/cache/files'])显式隔离不同 lock 版本 - 避免把整个
.composer/cache当作单一 cache path —— metadata 和 vcs 缓存对租户敏感,混用会导致依赖解析错误 - 如果租户间 PHP 版本或扩展不一致(如 ext-opcache 开关差异),即使 lock 相同,也应禁用跨租户 overlay,改用 per-tenant lowerdir
OverlayFS 是底层加速手段,不是逻辑一致性保障;缓存是否生效,最终取决于 Composer 运行时看到的 lock 内容和环境约束是否匹配。










