欢迎光临

Docker 训练保存 checkpoint 报 Permission denied:UID、GID 与挂载权限排查

开发者在 Linux 终端排查 Permission denied 写权限错误,AI 生成写实配图
AI 生成写实配图,展示本文讨论的工作场景。

训练跑了几个小时,保存 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 日。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Docker 训练保存 checkpoint 报 Permission denied:UID、GID 与挂载权限排查
分享到: 更多 (0)