
训练跑了几个小时,保存 checkpoint 时才报 PermissionError。GPU 识别成功并不保证进程能写入挂载目录。应当在正式训练前,用训练相同的身份完成一次写入、重命名和删除临时文件的验证。
本文命令面向原生 Linux Docker Engine 的普通 bind mount,默认未启用 rootless 或 user namespace remapping。Docker Desktop、NFS 和启用身份映射的环境在后文分别说明。所有修改仅作用于你确认的训练输出目录。
一、先确认报错路径真的落在挂载点
docker inspect train-job --format '{{json .Mounts}}'
docker exec train-job sh -c 'id; ls -ldn /output; test -w /output && echo writable'
# 宿主机上检查实际 Source 路径
ls -ldn /srv/training-output
namei -l /srv/training-output
容器进程还在运行时使用 docker exec,并确认执行检查的身份与训练进程相同。检查 Mounts 中的 Source、Destination 和 RW。路径拼错、挂载覆盖镜像原有内容、只读挂载,都可能让权限诊断偏离实际问题。
参考资料 · Docker bind mount 路径、只读标志和挂载行为
二、用数字 UID/GID 比对身份
在普通 Linux bind mount 中,内核根据数字身份和权限判断访问。容器内用户名叫 trainer,宿主机用户名叫 alice,名字本身不能证明它们具有相同权限。目录可创建文件需要写和执行权限,完整路径的父目录也需要可遍历。
以下在 Linux 宿主机创建一个独立测试目录。镜像使用项目已经拉取并固定版本的训练镜像,示例要求镜像包含 sh、Python,能以指定数字用户运行。
checkpoint_dir="$(mktemp -d "$PWD/checkpoint-demo.XXXXXX")" chmod 700 "$checkpoint_dir" export TRAIN_IMAGE='your-validated-training-image:version' docker run --rm \ --user "$(id -u):$(id -g)" \ --mount "type=bind,src=$checkpoint_dir,dst=/output" \ "$TRAIN_IMAGE" sh -c 'id; python -c "from pathlib import Path; p=Path(\"/output/probe.tmp\"); p.write_text(\"ok\"); p.replace(\"/output/probe.done\"); Path(\"/output/probe.done\").unlink(); print(\"WRITE_OK\")"'
指定 UID/GID 以后,镜像可能还需要可写 HOME、缓存目录或用户配置。这些路径应独立设置。如果输出目录是项目组共享目录,在宿主机配置目标组和 setgid 目录,再向容器传入相应的 –group-add 数字组。容器进程的附加组并不会自动等同于宿主机登录用户。
参考资料 · Docker 运行用户和附加组配置
三、共享目录只授予必要的组权限
下面由目录所有者或管理员操作,目标组 trainer 的 GID 必须与容器附加组一致。先核对目录是否专用于本项目,避免改动他人已有训练文件。
# 先确认目标路径和组 ls -ldn /srv/training-output getent group trainer # 经核对后,仅修改这个目录本身 sudo chgrp trainer /srv/training-output sudo chmod 2770 /srv/training-output # 运行时追加 --group-add 对应的数字 GID
setgid 使新建内容继承目录组,但文件是否组可写仍受程序创建模式和 umask 影响。已有文件也不会因此自动获得新权限。继续检查要覆盖的文件,必要时对明确选定的文件设置权限或 ACL,并重新运行探针。
四、普通权限正确时,检查这些额外限制
| 场景 | 核对方向 |
|---|---|
| 只读挂载 | 检查 RW、ro,以及宿主机文件系统是否只读 |
| SELinux | 检查审计拒绝和目录标签,按实际共享关系评估 :z 或 :Z,谨慎限定重标记路径 |
| rootless / userns-remap | 容器数字 UID 可能映射为其他宿主机 UID,按映射和存储设计检查 |
| NFS | 核对服务端权限、ACL、UID 一致性及 root_squash |
| Docker Desktop | 检查文件共享授权和宿主机 ACL,权限语义与原生 Linux 有差别 |
| ENOSPC / EDQUOT | 分别检查磁盘空间、inode 和配额,保留原始 errno |
参考资料 · user namespace 身份映射与挂载限制
五、把写入探针放到训练启动前
探针使用与训练相同的运行用户和挂载配置,在真实输出目录创建唯一命名的小文件,写入后执行同目录重命名,再清理探针文件。分布式训练检查真正保存 checkpoint 的 rank 和路径,同时验证容器重建后的恢复读取。
验证范围:本篇命令按 Docker 官方权限与挂载语义编写,当前环境未进行 Linux Docker 容器实测。读者应先在独立测试目录运行探针,再调整正式训练目录。本篇集中处理文件写权限,GPU runtime 报错可查阅站内对应排错文章。
配套文件与同系列文章
本文命令可直接从正文复制,先在独立测试目录验证。技术文档核对日期为 2026 年 11 月 10 日。
汤不热吧