PHP写文件失败需排查容器权限、路径存在性及挂载设置;常见报错定位点包括进程用户、目录属主权限、宿主机挂载配置;Docker启动时应统一UID、加SELinux标签或预设宿主机目录权限;代码中须用is_writable()和filesize()双重校验。
行,但得看容器里 PHP 进程有没有写权限、目标路径是否存在、挂载方式是否允许写入——不是“能运行 file_put_contents()”就等于“文件真能落盘”。
遇到 file_put_contents(): failed to open stream: Permission denied 或 No such file or directory,别急着改代码

www-data 或 root),用 ps aux | grep php 或 id 确认/var/www/html/uploads)在容器内的属主和权限:ls -ld /var/www/html/uploads
-v /host/path:/container/path)?如果是,宿主机对应路径的权限和 SELinux(Linux)或 file sharing(Mac)设置也会影响容器内写入不改代码也能让 file_put_contents() 成功,关键在启动容器时把权限铺平:
--user 指定与目标目录属主一致的 UID,例如 --user 33:33(对应 www-data):z 或 :Z(仅限 SELinux 启用的 Linux 宿主机),如 -v ./uploads:/var/www/html/uploads:z
mkdir -p uploads && chmod 777 uploads(开发环境可接受;生产慎用)即使容器配置没问题,file_put_contents() 仍可能静默失败。务必补上这两步:
is_writable($dir) 检查目录是否真正可写,别只信 is_dir()
file_exists() + filesize() 验证文件是否生成且非空,尤其当目标是挂载卷时,NFS 或某些 Docker Desktop 共享机制会导致写入延迟或截断示例片段:
if (!is_writable('/var/www/html/uploads')) {
error_log('Upload dir not writable');
exit;
}
$result = file_put_contents('/var/www/html/uploads/test.txt', 'hello');
if ($result === false || filesize('/var/www/html/uploads/test.txt') === 0) {
error_log('Write failed or file empty');
}
docker-compose.yml 里写 volumes: 很方便,但默认挂载行为在不同平台表现不一:
osxfs 对 chmod 和 chown 支持有限,容器内 chown www-data:www-data /uploads 可能无效chown,需改用 WSL2 原生路径(如 /home/user/project)再挂载init: true 或自定义 entrypoint,确保它没在启动 PHP 前意外重置了目录权限最稳的做法:把上传目录放在容器内部(非挂载),只在需要持久化时用 docker cp 或定期同步到宿主机——尤其适合 CI/CD 或临时调试场景。