tao-run-on-local-docker について
TAO Local Docker は、ローカルまたはリモートの Docker デーモン上で TAO ジョブを名前付きコンテナとして実行する単一ノード向けプラットフォームです。開発、デバッグ、小規模実行を対象とし、マルチノードのスケジューリングには対応しません。
主な機能
- 01Docker デーモン経由の TAO ジョブ実行
- 02ローカルおよびリモート Docker の利用
- 03単一ホストでの複数 GPU 利用
- 04起動前提条件の確認
- 05コンテナのマウントと実行 ID の設定
活用シーン
- 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 コンテナとして実行する単一ノード実行プラットフォームです。デーモンはエージェントホスト上でローカルに実行することも、DOCKER_HOST=ssh://user@host または Docker コンテキストを通じてリモートで実行することもできます。開発、デバッグ、小規模な実行、ローカルのコーディングエージェントがリモートの GPU サーバーにジョブを送信するワークフローに便利です。
データが Docker ホスト上にある場合、またはマウントされたボリューム/クラウド認証情報を通じてアクセスできる場合は、ローカル Docker を使用してください。リモートクラスタのスケジューリング、マルチノードトレーニング、SLURM キューイングが必要なジョブには使用しないでください。
エージェントがワークステーションやノート PC 上で実行されていて、Docker デーモンと GPU が別の単一 GPU サーバー上にある場合は、リモート Docker を使用してください。リモート Docker モードでは、仕様内のすべてのローカルファイルシステムパスは、エージェントマシンではなくリモート Docker ホスト上のパスとして解釈されます。
事前確認
ワークフローでは、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
確認に失敗した場合、エージェントは続行する前に、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:リモート SLURM 子ジョブの監視に SSH キーが必要な場合、AutoML ブレインコンテナにマウントされます。
- ACCESS_KEY、SECRET_KEY、S3_ENDPOINT_URL、S3_BUCKET_NAME: ローカルコンテナからクラウドストレージの読み書きを行うジョブ向けの、任意の S3 互換ストレージ設定です。
起動前チェック
スクリプトを生成したりコンテナを起動したりする前に、次の項目を確認します。
- Docker デーモンに接続できること、NVIDIA Container Toolkit が Docker ランタイムとして登録されていること、GPU とドライバーバージョンが報告されること、起動前にスモークテスト用コンテナから GPU が認識できることを確認します。リモート Docker の場合は、リモートデーモンに対して
docker run ... nvidia-smiを実行して GPU を確認します。エージェントマシン上でローカルのnvidia-smiは使用しないでください。 - すべてのローカル/ファイルデータセットのアノテーションパスとメディアパスが Docker ホスト上に存在することを確認します。
- すべてのバインドマウントを読み取り専用または書き込み可能に分類します。書き込み可能なマウントでは、デフォルトで Docker ホストユーザーの数値 UID:GID を使用し、コンテナの ID(
USER/LOGNAME)と HOME/フレームワークキャッシュのパスを設定して、その ID で書き込み可能にする必要があります。Docker を直接実行する場合は、これらを明示的に渡す必要があります(「非 root コンテナの ID」を参照)。SDK は書き込み可能な/resultsバインドの下にこれらを準備します(強制的に非 root で実行するジョブで/resultsがない場合に限り、分離された/tmpを代わりに使用します)。リモート Docker の場合は、エージェントのノート PC の数値 ID を転用せず、リモートホスト上で ID を解決します。 s3://データセット/結果の場合は、ACCESS_KEYとSECRET_KEYが設定されていること、およびaws s3 lsで正確なパスを読み取れることを確認します。awsがない場合は、不足している依存関係を報告し、インストール前にユーザーに確認します。インストール後、起動前チェックを再実行します。- 起動前に、
HF_TOKENなどモデル固有の認証情報を確認します。 nvidia-smiで現在の 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 ホスト上に存在する必要があります。ローカルのノート PC または Codex ホスト上にしか存在しないパスは渡さないでください。
リモート Docker ホスト上で実際にジョブを送信するユーザーの UID:GID を解決し、その ID を明示的に SDK に渡します。クライアントのノート PC の 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 コンテナの ID
--user <uid>:<gid> だけでは不十分です。TAO イメージで非 root アカウントが用意されているのは UID 1000(ubuntu と taotoolkituser。この UID では両者が競合します)のみです。そのため、それ以外の数値 UID では /etc/passwd にエントリがない状態で実行されます。この問題は UID 1000 のワークステーションでは表面化せず、ほかのすべての環境で再現します。getpass.getuser() は pwd.getpwuid() にフォールバックする前に LOGNAME/USER/LNAME/USERNAME を読み取るため、どれも設定されていないと、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 中にインダクターキャッシュディレクトリを初期化する際、この呼び出しに到達するため、コンテナは起動時に終了コード 1 で終了します。また Docker は、未知の UID に対して HOME=/ のままにするため、フレームワークのキャッシュがイメージ所有のパスに書き込まれます。
したがって、--user を渡すすべての Docker 直接起動では、ID とキャッシュ環境変数も渡す必要があります。これらは SDK が docker_handler.py で設定するものと一致させてください。どちらかを変更する場合は、2 つのリストを同期させてください。
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 エントリが実際に存在しない ID を表し、キャッシュパスの命名にのみ使用されます。起動時の getpwuid エラーを回避するために --user を外さないでください。そうすると、起動エラーよりも修復コストの高い、root 所有の出力が生じます。
マルチ GPU とマルチノード
ローカル Docker ではマルチノードはサポートされていません。 ジョブはローカル Docker デーモンのホスト上で実行され、ホスト間の連携は行われません。
ローカルホスト上のマルチ GPU は、NVIDIA Container Toolkit の --gpus フラグ(--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>"]です。 - コンテナはデタッチモードで実行されます。
DOCKER_AUTO_REMOVE=trueの場合を除き、ステータスとログを引き続き確認できるよう、SDK はデフォルトでコンテナを保持します。 - デフォルトの
run_as_user=Noneでは、書き込み可能な絶対パスの/resultsバインドがある場合、SDK はローカルジョブを呼び出し元の UID:GID にマッピングし、ローカルの補助グループを保持して、/results/.tao-runtime/homeの下に HOME/フレームワークのキャッシュを用意します。run_as_user=Trueを指定すると、他のローカルマウント構成でもユーザーマッピングが有効になります。SDK プロセス自体が root の場合、自動マッピングは0:0にマッピングせず、安全のため失敗します。その場合は、確認済みのジョブを送信する非 root の UID:GID をcontainer_userで指定してください。container_userは、リモートホストに対する明示的な非 root の Docker ユーザー上書きにも使用されます。run_as_user=Falseは、root が必要だと確認済みのイメージに対する意図的なオプトアウトです。 /dev/shmは tmpfs としてマウントされます。- 設定された Docker ネットワークは、ジョブコンテナに対して Docker デーモンによって適用されます。プロセスの環境変数として渡されることはありません。
- 同じジョブ ID の既存のコンテナは、置き換えコンテナの起動前に停止され、削除されます。
GPU アクセスについて、ハンドラーはホストの種類を自動検出します。
- Tegra または Jetson ホストでは、
runtime="nvidia"に加えて、NVIDIA_VISIBLE_DEVICESとNVIDIA_DRIVER_CAPABILITIES=allを使用します。 - 標準的な x86 ホストでは、GPU 機能を指定した Docker の
device_requestsを使用します。
num_gpus が 0 の場合、GPU は割り当てられません。num_gpus が -1 の場合、認識可能なすべての GPU が要求されます。開発者が共有するマシンでは、明示的な GPU 数を指定してください。明示的なデバイス ID を指定できる場合は、共有マシンで台数だけを指定する方法よりも、デバイス ID の指定を優先してください。これにより、他のタスクが使用中の GPU を起動時に奪うことを防げます。
ストレージ
ローカルの Docker は、コンテナが同じ Docker ホスト上で実行されるため、ローカルパスと file:// パスを受け付けます。仕様内のすべてのパスが、次のいずれかに該当することを確認してください。
- ハンドラーまたは周辺サービスによってコンテナにマウントされている
- すでにコンテナ内からアクセスできる
- 対応する認証情報を備えたクラウド URI である
バインドマウントされた出力では、ホストユーザーの所有権は起動時の不変条件であり、権限エラーへの対処法ではありません。root コンテナは、チェックポイントのサブディレクトリを root:root のモード 0755 で作成することがよくあります。トップレベルの出力ディレクトリがあらかじめ作成されていても、ホストユーザーはその中のファイルを削除できません。コンテナの自動削除を行っても、バインドマウントされた出力はそのまま残ります。
選択したイメージで root が必要だと明確に確認できた場合に限り、ホストユーザーのマッピングを無効にしてください(run_as_user=False)。その例外を起動レビューに記録し、書き込み可能なマウントを分離したうえで、すべてのプロセス終了およびキャンセル後に、すべての出力/キャッシュのマウントを Docker ホストの UID:GID に戻してください。リモート Docker の場合は、クライアントマシンや出力ディレクトリの所有者から推測せず、確認済みのリモートホストの非 root ユーザーを container_user で指定してください。所有権の正規化が成功するまで、次の実験を開始しないでください。エージェントにその修復を実施または検証する権限がない場合、root が必要なイメージはローカル Docker で起動できません。
AutoML のデフォルトのチェックポイント保持設定はさらに厳格です。SDK がホスト側での削除を保証できないため、試行の起動前に、run_as_user=False、名前付きボリューム、リモートのバインドマウント、または互換性のない container_user の明示的な指定を事前チェックで拒否します。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 ランタイムが管理し、TAO Core のローカル GPU マネージャーは管理しません。
任意:TAO SDK 経由
ジョブハンドル、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)
これは、同じ docker run 呼び出しを Job ハンドルでラップします。S3 I/O を行う場合は、先に build_entrypoint(...) を呼び出し、そのコマンドを渡してください。これにより、script_runner が宣言されたダウンロード/アップロードを実行できます。ジョブの追跡やこのラッパーが不要な場合は、docker run を直接使用してください。SDK のインストールは不要です。
失敗モード
Docker クライアントが初期化されていません:Docker Python パッケージがインストールされていることを確認してください。デフォルトのローカルソケットを使用しない場合は DOCKER_HOST を設定し、プロセスがデーモンと通信できることを確認してください。
GPU の割り当てに失敗しました:要求した GPU を利用できない、NVIDIA Container Toolkit が設定されていない、または Docker デーモンが GPU デバイス要求を作成できない可能性があります。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 コンテナーの ID」に記載された ID とキャッシュ環境を追加してください。root として実行する方法に切り替えないでください。
コンテナー内にパスがありません:ホスト上のローカルパスがジョブコンテナーにマウントされているとは限りません。アクションランナーがサポートするパス規則を使用するか、周辺サービスを通じて明示的なボリュームを設定してください。
bind マウントされた結果ファイルの所有者が root です:新しい実験の起動を停止し、docker inspect で書き込み可能なマウントをすべて特定したうえで、ホスト管理者に既存の所有権を一度修復してもらってください。今後の起動では、ホストの UID:GID マッピングと、書き込み可能な HOME/キャッシュのリダイレクトを使用する必要があります。docker rm と DOCKER_AUTO_REMOVE では、bind マウントされたファイルの所有権は修復されず、ファイルも削除されません。