关于 tao-run-on-local-docker
TAO Local Docker 是单节点执行平台,可将 TAO 作业作为命名 Docker 容器运行,连接本地或远程 Docker 守护进程。适用于开发、调试和小规模运行,不提供多节点调度。
主要功能
- 01通过 Docker 守护进程运行 TAO 作业
- 02支持本地与远程 Docker
- 03支持单机多 GPU
- 04执行启动前置检查
- 05配置容器挂载与身份
适用场景
- 01在本地 GPU 主机上开发和调试
- 02从工作站向远程单 GPU 服务器提交作业
- 03运行不需要集群调度的单节点训练
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nvidia/ skills --skill tao-run-on-local-docker安装后在 Claude Code 中输入/tao-run-on-local-docker确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
BENCHMARK.mdskill-card.mdskill.oms.sigconfig/skillspector-baseline.yamlevals/evals.jsonreferences/skill_info.yaml详细介绍
本地 Docker
单独安装? 如果此会话不是由 TAO 技能库插件初始化的,请先运行
tao-setup技能(主机预检、凭据、跨技能发现)。
单节点执行平台,可在 Docker 守护进程上将 TAO 作业作为命名 Docker 容器运行。守护进程可以位于 Agent 主机本地,也可以通过 DOCKER_HOST=ssh://user@host 或 Docker 上下文连接远程守护进程。它适用于开发、调试、小规模运行,以及由本地编码 Agent 向远程 GPU 机器提交作业的工作流。
当数据位于 Docker 主机本地,或可通过挂载卷/云凭据访问时,请使用本地 Docker。对于远程集群调度、多节点训练或需要使用 SLURM 队列的作业,请勿使用本地 Docker。
当 Agent 在工作站或笔记本电脑上运行,而 Docker 守护进程和 GPU 位于另一台 GPU 服务器上时,请使用远程 Docker。在远程 Docker 模式下,规范中的所有本地文件系统路径都会在远程 Docker 主机上解析,而不是在 Agent 机器上解析。
预检
工作流必须在启动 Docker 作业前验证主机 GPU 运行时。如果检查失败,请提示用户批准安装,运行打印出的安装命令,然后重新运行预检。
# Host GPU runtime: NVIDIA driver 580, CUDA 13.0, NVIDIA Container Toolkit 1.19.0.
SB="${TAO_SKILL_BANK_PATH:-${TAO_SKILL_BANK_ROOT:-$PWD}}"
SETUP_SCRIPT="${SB}/skills/platform/tao-setup-nvidia-gpu-host/scripts/setup-nvidia-gpu-host.sh"
bash "$SETUP_SCRIPT" --backend docker --check-only || {
echo "MISSING: TAO GPU host runtime is not ready."
echo "After user approval, run:"
echo " bash \"$SETUP_SCRIPT\" --backend docker --install --yes"
exit 1
}
# Mode 1 — direct docker (no Python). All you need is docker + the GPU runtime.
docker info >/dev/null 2>&1 || { echo "MISSING: docker daemon not reachable. Start Docker."; exit 1; }
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi >/dev/null 2>&1 || {
echo "MISSING: NVIDIA Container Toolkit not installed/configured. See:"
echo " bash \"$SETUP_SCRIPT\" --backend docker --install --yes"
exit 1
}
# Mode 2 — TAO SDK wrapper. Adds Job handles, S3 I/O wrapping, ActionWorkflow.
# Skip this block if Mode 1 is sufficient for the user's request.
# When Mode 2 is in scope, read `tao-skill-bank:tao-run-platform` for the DockerSDK
# kwarg contract, build_entrypoint, and monitoring patterns.
# nvidia-tao-sdk is on public PyPI; the pin below is stamped from the release manifest.
PIN="nvidia-tao-sdk[docker]==7.1.0rc42" # versions-key: wheels.tao_sdk_docker
python -c "import tao_sdk" 2>/dev/null || python -m pip install "$PIN"
python -c "import docker" 2>/dev/null || python -m pip install "$PIN"
python -c "import tao_sdk, docker"
# DockerSDK attaches every job container to ${DOCKER_NETWORK:-tao_default}.
# Create the network if it is missing; the operation is local and idempotent.
DOCKER_NETWORK_NAME="${DOCKER_NETWORK:-tao_default}"
docker network inspect "$DOCKER_NETWORK_NAME" >/dev/null 2>&1 || \
docker network create "$DOCKER_NETWORK_NAME" >/dev/null
如果检查失败,Agent 会提示用户通过 Bash 授权安装/修复,然后再继续。可通过 pip 安装的 Python 依赖项以及上文所述的 Docker 网络创建操作除外:请自动安装/创建它们,然后重新运行预检。
凭据
除了访问 Docker 守护进程外,平台不需要其他凭据。
可选环境变量:
- DOCKER_HOST:可选的 Docker 守护进程 URL。如果未设置,SDK 会使用 Docker Python 客户端的常规环境/默认套接字解析方式。使用
remote-docker平台选项时必须设置。 - DOCKER_NETWORK:作业容器使用的 Docker 网络。默认值为
tao_default。 - DOCKER_USERNAME:镜像仓库用户名。NGC 的默认值为
$oauthtoken。 - NGC_KEY:从
nvcr.io拉取私有镜像时使用。 - HOST_SSH_PATH:当 AutoML brain 容器需要 SSH 密钥来监控远程 SLURM 子作业时,将此路径挂载到容器中。
- ACCESS_KEY、SECRET_KEY、S3_ENDPOINT_URL、S3_BUCKET_NAME: 作业仍需从本地容器读写云存储时可选的兼容 S3 存储设置。
启动前检查
生成脚本或启动容器之前:
- 确认 Docker 守护进程可访问、NVIDIA Container Toolkit 已注册为 Docker 运行时、GPU 和驱动程序版本均有报告,并且启动前的冒烟测试容器能够看到 GPU。对于远程 Docker,应通过针对远程守护进程运行
docker run ... nvidia-smi来查询 GPU;不要在 Agent 机器上使用本地nvidia-smi。 - 确认 Docker 主机上存在每个本地/文件数据集的标注和媒体路径。
- 将每个绑定挂载分类为只读或可写。默认情况下,可写挂载必须使用 Docker 主机用户的数字 UID:GID,并且必须为该身份设置可写的容器身份(
USER/LOGNAME)和 HOME/框架缓存路径。直接使用 Docker 时必须显式传递这些值(参见“非 root 容器身份”);SDK 会在可写的/results绑定挂载下准备这些路径(仅当强制使用非 root 身份的作业没有此挂载时,才会使用隔离的/tmp作为备用路径)。对于远程 Docker,应在远程主机上解析身份,而不是照搬 Agent 笔记本电脑上的数字 ID。 - 对于
s3://数据集/结果,确认已设置ACCESS_KEY和SECRET_KEY,并且可以通过aws s3 ls读取准确路径。如果缺少aws,请报告缺少的依赖并先征求安装许可;安装后重新执行启动前检查。 - 启动前确认模型所需的凭据,例如
HF_TOKEN。 - 使用
nvidia-smi检查当前 GPU 占用情况;如果用户要求避开正在被其他运行作业使用的 GPU,就不要选择这些 GPU。在启动审核中显示所选 GPU ID。 - 对于已知存在架构限制的模型/容器组合,启动前比较主机 GPU 的计算能力与容器堆栈。如果所选镜像无法为主机架构执行 JIT 或运行内核,则应尽早阻止启动,并请求用户提供兼容的镜像或平台。
尽可能使用随附的辅助工具完成这些检查:
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/check_tao_launch_preflight.py \
--platform local-docker \
--container-image "<selected-image>" \
--path train_annotation=/abs/path/to/annotations.json \
--path train_media=/abs/path/to/media
对于远程 Docker 守护进程,请使用 remote-docker 平台并传入或导出
DOCKER_HOST。辅助工具会验证远程 GPU/运行时是否就绪,并通过只读绑定挂载检查
远程主机上的数据集路径:
${TAO_SKILL_BANK_PATH:-~/tao-skills-external}/scripts/check_tao_launch_preflight.py \
--platform remote-docker \
--docker-host ssh://user@gpu-host \
--container-image "<selected-image>" \
--gpu-smoke-image ubuntu:22.04 \
--path train_annotation=/remote/data/train/annotations.json \
--path train_media=/remote/data/train
上方的 --path 值必须存在于远程 Docker 主机上。不要传入仅存在于本地笔记本电脑或 Codex 主机上的路径。
在远程 Docker 主机上解析实际提交用户的 UID:GID,然后将该身份显式传递给 SDK。不要沿用客户端笔记本电脑的 UID:GID,也不要根据共享输出目录的 stat 所有权推断容器用户:该目录可能属于 root:<shared-group>,也可能由其他组成员拥有。
REMOTE_RESULTS=/remote/results
# Use the same SSH account represented by DOCKER_HOST=ssh://user@gpu-host,
# or obtain these two values from the remote administrator.
REMOTE_UID="$(ssh user@gpu-host id -u)"
REMOTE_GID="$(ssh user@gpu-host id -g)"
case "$REMOTE_UID" in
''|*[!0-9]*|0)
echo "A verified non-root remote submitting UID is required."
exit 1
;;
esac
case "$REMOTE_GID" in
''|*[!0-9]*)
echo "A verified numeric remote submitting GID is required."
exit 1
;;
esac
TAO_DOCKER_CONTAINER_USER="$REMOTE_UID:$REMOTE_GID"
export TAO_DOCKER_CONTAINER_USER
# Prove that this exact identity can create and remove a child in the bind.
docker --host "$DOCKER_HOST" run --rm \
--user "$TAO_DOCKER_CONTAINER_USER" \
-v "$REMOTE_RESULTS:/ownership-probe" ubuntu:22.04 \
sh -c 'p=/ownership-probe/.tao-write-delete-probe-$$; touch "$p" && rm "$p"' || {
echo "Remote submitting identity cannot write/delete under $REMOTE_RESULTS."
exit 1
}
非 root 容器身份
仅设置 --user <uid>:<gid> 还不够。TAO 镜像仅为 UID 1000 配置了非 root 账户(ubuntu 和 taotoolkituser 在此处发生冲突),因此其他所有数字 UID 运行时都没有 /etc/passwd 条目。这会导致问题在 UID-1000 工作站上不易察觉,却能在其他所有地方复现。getpass.getuser() 会读取 LOGNAME/USER/LNAME/
USERNAME,然后才回退到 pwd.getpwuid();因此,如果这些变量均未设置,查找会在任何 TAO 代码运行之前抛出异常:
File "/usr/lib/python3.12/getpass.py", line 169, in getuser
return pwd.getpwuid(os.getuid())[0]
KeyError: 'getpwuid(): uid not found: 1002'
Torch 在 import 期间初始化其 inductor 缓存目录时就会调用该函数,因此容器会在启动时以状态码 1 退出。对于未知 UID,Docker 还会将 HOME=/ 保留下来,导致框架缓存写入镜像所属的路径。
因此,所有传入 --user 的直接 Docker 启动都必须同时传入身份和缓存环境变量。这些设置与 SDK 在 docker_handler.py 中注入的内容一致;任一列表发生变化时,都要同步更新两份列表。
HOST_UID="$(id -u)"; HOST_GID="$(id -g)"
TAO_HOME=/results/.tao-runtime/home # must live on a writable mount
mkdir -p "$RESULTS_DIR/.tao-runtime/home"
docker run --rm --gpus all --ipc=host \
--ulimit memlock=-1 --ulimit stack=67108864 \
--user "$HOST_UID:$HOST_GID" \
-e USER="$HOST_UID" -e LOGNAME="$HOST_UID" \
-e HOME="$TAO_HOME" \
-e XDG_CACHE_HOME="$TAO_HOME/.cache" \
-e HF_HOME="$TAO_HOME/.cache/huggingface" \
-e TORCH_HOME="$TAO_HOME/.cache/torch" \
-e TRITON_CACHE_DIR="$TAO_HOME/.cache/triton" \
-e TORCHINDUCTOR_CACHE_DIR="$TAO_HOME/.cache/torchinductor" \
-e MPLCONFIGDIR="$TAO_HOME/.cache/matplotlib" \
-v "$DATA_DIR:/data:ro" -v "$RESULTS_DIR:/results" -v "$SPECS_DIR:/specs:ro" \
"$IMAGE" <action> train -e /specs/<spec>.yaml
使用数字形式的 USER/LOGNAME 是有意为之:它们描述的身份确实没有 passwd 条目,而且仅用于缓存路径命名。不要为了绕过启动时的 getpwuid 错误而删除 --user——这样只会把启动错误换成由 root 拥有的输出;后者的修复代价更高。
多 GPU 和多节点
本地 Docker 不支持多节点。 单个作业运行在本地 Docker 守护进程所在的主机上,不进行跨主机协调。
支持在本地主机上使用 NVIDIA Container Toolkit 的 --gpus 标志启用多 GPU(--gpus all 或 --gpus '"device=0,1,2,3"')。DockerSDK.create_job(gpu_count=N) 会将参数传递给 --gpus。单主机分布式初始化使用 localhost;torchrun --nproc-per-node=N 或 PyTorch DDP 均可照常工作。
后端详情
使用 SDK 后端值 local-docker。本地后端架构没有额外的
后端详情,因此大多数路由由环境和作业
参数控制:
{
"backend_type": "local-docker",
"num_gpu": 1
}
遵循 Brev SDK 的设计,平台/控制平面值保留在 SDK
状态和 Docker 标签中。SDK 不会将 BACKEND、HOST_PLATFORM、
MONGOSECRET、DOCKER_HOST 或 DOCKER_NETWORK 注入训练容器。
容器执行
TAO SDK 本地 Docker 处理程序通过 Docker Python 客户端启动容器:
- 后端作业名称采用 SDK 处理程序使用的
tao-job-<job_id>格式。 - 命令通常为
["/bin/bash", "-c", "<job command>"]。 - 容器以分离模式运行。默认情况下,SDK 会保留容器,以便仍可检查状态和
日志,除非设置
DOCKER_AUTO_REMOVE=true。 - 在
run_as_user=None(默认值)时,如果本地作业有一个可写的绝对路径/results绑定,SDK 会将其映射到调用者的 UID:GID,保留本地补充组,并在/results/.tao-runtime/home下准备 HOME/框架缓存。设置run_as_user=True可为其他本地挂载布局启用 用户映射。如果 SDK 进程本身以 root 身份运行,自动映射会安全失败,而不会映射到0:0;请通过container_user提供已验证的提交者非 root UID:GID。container_user也可显式覆盖远程主机上的非 root Docker 用户。对于已确认需要 root 权限的镜像,可通过run_as_user=False有意选择不进行映射。 /dev/shm以 tmpfs 形式挂载。- 配置的 Docker 网络由 Docker 守护进程应用于作业容器;它不会作为进程环境变量传递。
- 启动替代容器前,会停止并移除具有相同作业 ID 的现有容器。
对于 GPU 访问,处理程序会自动检测主机类型:
- Tegra 或 Jetson 主机会使用
runtime="nvidia",并设置NVIDIA_VISIBLE_DEVICES和NVIDIA_DRIVER_CAPABILITIES=all。 - 标准 x86 主机会使用 Docker
device_requests和 GPU 功能。
如果 num_gpus 为 0,则不会分配 GPU。如果 num_gpus 为 -1,则会请求所有可见
GPU。在共享开发机器上,建议指定明确的 GPU 数量。如果有明确的设备 ID,在共享机器上应优先使用设备 ID,而不是仅按数量选择,以免启动时占用其他任务正在使用的 GPU。
存储
本地 Docker 接受本地路径和 file:// 路径,因为容器运行在同一 Docker 主机上。请确保规范中的每个路径满足以下条件之一:
- 由处理程序或外围服务挂载到容器中;
- 已可从容器内部访问;或
- 是具有相应凭据的云 URI。
对于绑定挂载的输出,以主机用户身份运行是启动时的必要条件,而不是用于绕过权限错误的方法。以 root 身份运行的容器通常会以 root:root 所有权和 0755 权限创建检查点子目录;即使顶层输出目录是预先创建的,主机用户也无法删除其中的文件。容器自动移除也不会影响绑定挂载的输出。
只有在能够明确证明所选镜像需要 root 权限时,才可关闭主机用户映射(run_as_user=False)。请在启动审核中记录这一例外,隔离其可写挂载,并在所有终端退出和取消操作后,将每个输出/缓存挂载的所有权恢复为 Docker 主机的 UID:GID。对于远程 Docker,请通过 container_user 传入经过验证的远程主机非 root 身份;切勿根据客户端机器或输出目录所有者推断该身份。所有权恢复成功之前,不得开始其他实验。如果 Agent 无权执行或验证此修复,则不能在本地 Docker 上启动需要 root 权限的镜像。
AutoML 的默认检查点保留策略更为严格:在启动试验之前,其预检会拒绝 run_as_user=False、命名卷、远程绑定挂载或不兼容的显式 container_user,因为 SDK 无法保证在主机端删除文件。仅当明确禁用保留策略且由外部操作员负责清理产物时,AutoML 才可使用这些方式。
对于远程/共享文件系统,优先使用管理该文件系统的平台。例如,对于集群上的 Lustre 路径,请使用 SLURM 和 lustre:///...。
监控
- SDK 处理程序会直接映射 Docker 容器状态:created → Pending,running/restarting → Running,paused → Paused,退出代码为 0 → Complete,非零退出 → Error。
- 日志通过 Docker Python 客户端直接从指定容器获取(
docker logs tao-job-<job_id>)。
如果容器已退出、已停止、正在移除或无法找到,状态协调会将后端进程视为已终止。
取消
取消操作会停止指定容器。GPU 的占用由 Docker / NVIDIA runtime 管理,而不是由 TAO Core 的本地 GPU 管理器管理。
可选:通过 TAO SDK
如果你需要 Job 句柄、通过 SDK 的 script_runner 封装 S3 I/O,或需要跨会话保持状态:
import os
from tao_sdk.platforms.docker import DockerSDK
docker_host = os.environ.get('DOCKER_HOST', '')
is_remote = bool(docker_host) and not docker_host.startswith(('unix://', 'npipe://', '/'))
container_user = os.environ.get('TAO_DOCKER_CONTAINER_USER')
if is_remote and not container_user:
raise RuntimeError('Set TAO_DOCKER_CONTAINER_USER to the remote output owner UID:GID')
sdk = DockerSDK() # reads DOCKER_HOST, NGC_KEY, S3 creds from env
job = sdk.create_job(
image='nvcr.io/nvidia/tao/tao-toolkit:7.1.0-pyt', # versions-key: images.tao_toolkit.pyt
command='dino train -e /data/spec.yaml',
gpu_count=1,
mounts=[
{'host_path': '/host/data', 'container_path': '/data', 'read_only': True},
{'host_path': '/host/results', 'container_path': '/results'},
],
container_user=container_user,
)
status = sdk.get_job_status(job.id)
logs = sdk.get_job_logs(job.id, tail=200)
这会在 Job 句柄下封装相同的 docker run 调用。对于 S3 I/O,请先调用 build_entrypoint(...),并传入其命令,以便 script_runner 执行声明的下载/上传操作。如果你不需要作业跟踪或该封装,直接使用 docker run 即可——无需安装 SDK。
失败模式
Docker 客户端未初始化:确认已安装 Docker Python 包;如果未使用默认本地套接字,请设置 DOCKER_HOST,并确认进程可以与守护进程通信。
GPU 分配失败:请求的 GPU 不可用、未配置 NVIDIA Container Toolkit,或者 Docker 守护进程无法创建设备请求。请减少 GPU 数量、等待其他作业完成,或确认主机上的 docker run --gpus ... 可以正常运行。
镜像拉取身份验证失败:为私有 nvcr.io 镜像设置有效的 NGC_KEY,或在 Docker 主机上运行 docker login nvcr.io -u '$oauthtoken'。
容器意外退出:检查 docker logs tao-job-<job_id>、已配置的 DOCKER_NETWORK,以及 SDK 操作运行器生成的命令。
KeyError: getpwuid(): uid not found:启动时传入了 --user,但该 UID 在镜像的 /etc/passwd 中没有对应条目,且未传入 USER/LOGNAME。请添加“非 root 容器身份”中所述的身份信息和缓存环境变量;不要改为以 root 身份运行。
容器内路径缺失:主机上的本地路径不一定会挂载到作业容器中。请使用操作运行器支持的路径约定,或通过外围服务配置显式卷。
绑定挂载的结果文件归 root 所有:停止启动新实验,通过 docker inspect 找出所有可写挂载点,并让主机管理员一次性修复现有文件的所有权。今后的启动必须使用主机 UID:GID 映射,并将 HOME/缓存重定向到可写位置。docker rm 和 DOCKER_AUTO_REMOVE 不会修复或删除绑定挂载的文件。