在Cloud Run部署FoundryVTT容器遭遇EPERM权限错误
问题场景
在Cloud Run上部署felddy/foundryvtt容器时,为避免内存卷重启丢失数据,尝试挂载Cloud Storage存储桶作为持久化卷,但启动时出现权限错误:
2025-03-28 22:18:20.840 EDT FoundryVTT | 2025-03-29 02:18:20 | [[32minfo[39m] User Data Directory - "/data"
2025-03-28 22:18:22.513 EDT FoundryVTT | 2025-03-29 02:18:22 | [[31merror[39m] A fatal error occurred while trying to start the Foundry Virtual Tabletop server: EPERM: operation not permitted, utime '/data/Config/options.json.lock'
2025-03-28 22:18:22.976 EDT Container called exit(1).
2025-03-28 22:18:22.976 EDT Error: A fatal error occurred while trying to start the Foundry Virtual Tabletop server: EPERM: operation not permitted, utime '/data/Config/options.json.lock'
原因分析
Cloud Run挂载Cloud Storage桶使用Cloud Storage FUSE,该文件系统不支持utime系统调用,而FoundryVTT启动时创建锁文件或修改文件时间戳会触发此操作,导致权限拒绝错误。
解决方案
1. 改用Cloud Run原生持久化磁盘(推荐)
Cloud Run的GCE持久化磁盘支持完整的POSIX文件系统操作,完全适配FoundryVTT的文件读写需求:
- 创建GCE持久磁盘,配置为Cloud Run服务的持久化卷,挂载路径设为容器内的
/data。 - 确保Cloud Run服务账号拥有磁盘的读写权限,且容器运行用户(felddy/foundryvtt默认UID为1000)对挂载目录有读写权限。
2. 自定义镜像禁用文件锁(适配Cloud Storage桶)
如果必须使用Cloud Storage桶,可修改FoundryVTT启动参数禁用锁文件:
- 创建自定义Dockerfile:
FROM felddy/foundryvtt:latest CMD ["node", "/foundryvtt/resources/app/main.js", "--dataPath=/data", "--no-socket-lock"] - 构建镜像并推送到Google Artifact Registry。
- 重新部署Cloud Run服务使用该自定义镜像。
- 同时确认Cloud Run服务账号拥有
roles/storage.objectAdmin权限,确保能读写存储桶内文件。
3. 本地缓存+Cloud Storage同步
通过脚本实现本地内存卷与Cloud Storage的数据同步,兼顾性能与持久化:
- 在容器启动脚本中,用
gsutil rsync从Cloud Storage下载数据到/data目录。 - 在容器停止前,用
gsutil rsync将/data目录的修改同步回Cloud Storage。 - 可将同步逻辑写入自定义启动脚本,替换镜像默认启动命令。
内容的提问来源于stack exchange,提问作者splatman73

