tao-run-on-docker について
tao-run-on-docker は、単一 GPU ノードでモデルやデータのワークロードを Docker 実行する TAO スキルです。ローカルと SSH 接続先の Docker デーモンで、投入、状態確認、ログ取得、キャンセルを共通化します。
主な機能
- 014つのジョブ操作
- 02ローカルと SSH 接続の Docker
- 03GPU 選択とコンテナ設定
- 04バインドマウントまたは S3 のデータ準備
- 05ジョブ記録と状態の対応付け
活用シーン
- 01ローカル GPU ホストでモデルワークフローを実行
- 02リモート GPU マシンへジョブを投入
- 03ログや状態の確認、ジョブのキャンセル
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill tao-run-on-dockerインストール後、Claude Code で/tao-run-on-dockerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdeval.configskill-card.mdskill.oms.sigconfig/skillspector-baseline.yamlevals/evals.jsonreferences/skill_info.yaml詳細
NVIDIA GPU ワークロード向け Docker
単独でインストールする場合 このセッションが TAO skill bank プラグインによって初期化されていない場合は、最初に
tao-setupスキルを実行してください(ホストの事前確認、認証情報、スキル間の検出)。
Docker 実行プラットフォームは、モデル/データスキルの spec-bundle を実行するコンシューマーです。docker CLI を使って 4 つの動詞(submit/status/logs/cancel)を実装し、ローカルデーモン、または DOCKER_HOST=ssh:// を使ったリモート GPU マシン上で動作します。動詞(§ Execution)は、このファイルの残りの部分で説明する Docker の規約(GPU フラグ、マウント、NGC 認証、検査、エラーモード)の上に成り立っています。モデル/データスキルが委ねるのは、この「方法」です。単一ノードのみ対応しています。マルチノードには SLURM または Kubernetes を使用してください。
出典:Docker CLI の公式リファレンス(https://docs.docker.com/reference/cli/docker/)および NVIDIA Container Toolkit のドキュメント。
前提条件
- ホスト GPU ランタイム — デフォルトでは NVIDIA ドライバー
>=580、CUDA Toolkit>=13.0、NVIDIA Container Toolkit>=1.19.0が必要です。選択したモデルのreferences/skill_info.yamlにruntime_requirements.gpu_hostが宣言されている場合は、代わりにそれらの値をtao-setup-nvidia-gpu-hostに渡してください。そのワークフローではモデルの要件がデフォルト値より優先されます。 - Docker —
docker --versionが ≥ 20.10 を返す必要があります。インストール先:https://docs.docker.com/engine/install/ - NGC API キー —
nvcr.io/*からプルするために必要です。https://ngc.nvidia.com/ から取得してください。
set -a; source /path/to/.env; set +a # omit if already exported
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 (append --yes for non-interactive agent runs):"
echo " bash \"$SETUP_SCRIPT\" --backend docker --install"
exit 1
}
docker --version
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
[ -n "$NGC_KEY" ] || echo "NGC_KEY unset — cannot pull nvcr.io images"
選択したモデルで runtime_requirements.gpu_host が宣言されている場合は、対応する --min-driver-version、--min-cuda-version、--min-container-toolkit-version の値を、確認コマンドと承認済みのインストールコマンドの両方に追加してください。あるモデルのオーバーライドを無関係なワークフローに適用しないでください。
NGC 認証
set -a; source /path/to/.env; set +a # omit if already exported
echo "$NGC_KEY" | docker login nvcr.io -u '$oauthtoken' --password-stdin
再起動後も ~/.docker/config.json に保持されます。unauthorized エラーが発生した場合は再実行してください。
実行 — 4 つの動詞
spec-bundle は、job-record のみを変更する以下の 4 つの動詞を正確に実装して実行します。ステータス値は tao-artifacts の固定語彙(PENDING RUNNING COMPLETE ERROR CANCELED UNKNOWN)です。Docker のネイティブ状態は以下のように対応付けられ、遷移の message に生の状態が記録されます。$BANK = ${TAO_SKILL_BANK_PATH}。
submit
- 入力をステージングするには
tao-data-ioを使用します。ストレージ階層を選び、マウント引数とコンピュートフレームのパスを返します。Docker では通常 階層 A(ホストのディレクトリをバインドマウント、-v /host/data:/data)を使用するか、階層 C(S3 の認証情報を渡し、コンテナが取得)を使用します。コンピュートフレームのパスを記載した spec ファイルを<stage>/spec.yamlに作成します。 - 組み立てたコマンドをリントします。
redact_secrets.py lintに合格する必要があります(インラインのシークレットは不可。値を付けずに-e VARとして認証情報を渡します)。 - レコードを開きます — これにより ID が発行され、起動前に
results_dirが紐付けられます:JOB_ID=$("$BANK/scripts/tao_job_record.py" open \ --platform docker --image "$IMAGE" \ --network-arch "$ARCH" --action "$ACTION" \ --storage-tier "$TIER" --results-root "$RESULTS_ROOT") - デタッチモードで起動し、他の動詞からコンテナを見つけられるよう、コンテナ名を ID にします(終了したコンテナを検査できるよう、
--rmは無効のままにします):set -a; source /path/to/.env; set +a # omit if already exported CID=$(docker run -d --name "$JOB_ID" --label "tao-job=$JOB_ID" \ --gpus "$GPUS" --shm-size=8g \ -v "$STAGE:/workspace" \ -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e HF_TOKEN -e NGC_KEY \ "$IMAGE" <bundle command, reading /workspace/spec.yaml>) - RUNNING を記録します:
"$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state RUNNING --backend-ref "$CID"。
手順 3 を省略して submit すると ID がないため起動できません。これが「記録してから起動する」という不変条件です。
status
read -r st code < <(docker inspect --format '{{.State.Status}} {{.State.ExitCode}}' "$JOB_ID" 2>/dev/null) || st=missing
| docker の状態 | 語彙 |
|---|---|
created / restarting | PENDING |
running / paused | RUNNING |
exited、終了コード 0 | COMPLETE |
exited、終了コード ≠ 0 | ERROR |
dead / 見つからない | UNKNOWN(docker ps -a で確認) |
終端状態になったら mark してください。階層 C の場合は、docker rm を実行する前に tao-data-io で結果をアップロードします(コンテナにあるデータが唯一のコピーです)。
logs
docker logs --tail "${N:-200}" "$JOB_ID" # add -f to follow in-turn
cancel
docker rm -f "$JOB_ID"
"$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state CANCELED --source agent
ローカルとリモート(DOCKER_HOST)
別個の「リモート Docker」はありません。SSH で接続できるマシンをデーモンの接続先に指定します。
export DOCKER_HOST=ssh://user@gpu-host。上記のすべての動詞はバイト単位で同一です。
docker CLI がリクエストを SSH 経由でマーシャリングします(キーを再利用し、コマンドの
入れ子の引用符を避けます)。その結果、-v のバインドマウント元は、起動元ではなく
リモートホストのファイルシステムを参照します。データをそこにステージングするか(ティア A)、
コンテナ内で取得してください(ティア C)。sudo docker しか使えないホストでの代替手段:
ssh host 'sudo docker …'(同じスキルで、プレフィックスが異なります)。
docker run — 標準的なフラグ
set -a; source /path/to/.env; set +a # omit if already exported
HOST_RESULTS=/host/results
HOST_UID="$(id -u)"
HOST_GID="$(id -g)"
HOST_USER_NAME="$(id -un)"
[ "$HOST_UID" -ne 0 ] || { echo "Refusing writable Docker launch as UID 0" >&2; exit 1; }
HOST_IDENTITY_ARGS=(--user "$HOST_UID:$HOST_GID")
for group_id in $(id -G); do
[ "$group_id" = "$HOST_GID" ] || HOST_IDENTITY_ARGS+=(--group-add "$group_id")
done
mkdir -p "$HOST_RESULTS/.tao-runtime/home/.cache"/{huggingface,torch,triton,torchinductor,matplotlib}
docker run \
--gpus all \
--rm \
--shm-size=8g \
"${HOST_IDENTITY_ARGS[@]}" \
-v /host/data:/data \
-v "$HOST_RESULTS:/results" \
-e HOME=/results/.tao-runtime/home \
-e USER="$HOST_USER_NAME" -e LOGNAME="$HOST_USER_NAME" \
-e XDG_CACHE_HOME=/results/.tao-runtime/home/.cache \
-e HF_HOME=/results/.tao-runtime/home/.cache/huggingface \
-e TORCH_HOME=/results/.tao-runtime/home/.cache/torch \
-e TRITON_CACHE_DIR=/results/.tao-runtime/home/.cache/triton \
-e TORCHINDUCTOR_CACHE_DIR=/results/.tao-runtime/home/.cache/torchinductor \
-e MPLCONFIGDIR=/results/.tao-runtime/home/.cache/matplotlib \
-e HF_TOKEN -e NGC_KEY \
<image> \
<command>
注意事項:
--gpus '"device=0,1"'— 共有ホストでは、台数ではなく GPU ID を指定します(二重引用符をエスケープしています)。台数で指定すると、先頭から N 台が割り当てられるため、--gpus 1では必ず GPU 0 しか使えません。GPU 0 が使用中の場合、ほかの GPU がアイドル状態でも、すべてのジョブがそこで OOM になり、割り当て先を変更する方法はありません。-e NVIDIA_VISIBLE_DEVICESは--gpusに上書きされます。現在の使用状況を確認し(nvidia-smi --query-gpu=index,memory.used --format=csv)、空いている ID を指定してください。ID には GPU UUID も使えます。nvidia-container-toolkit がない場合:could not select device driver "" with capabilities: [[gpu]]。--rm— 終了時にコンテナをクリーンアップします。終了後にdocker logsを使う場合は省略してください。--shm-size=8g— デフォルトの 64 MB の/dev/shmでは、torchrun と PyTorch DataLoader の使用時に枯渇します。マルチ GPU トレーニングに合わせてサイズを設定し、それでもBus errorが発生する場合は、(例:16g)に増やしてください。--user "$(id -u):$(id -g)"— 書き込み可能なバインドマウントを使う場合は、デフォルトで必須です。これにより、送信元のホストユーザーがクリーンアップできない、root 所有のチェックポイントディレクトリが作られるのを防ぎます。- 標準的な書き込み可能バインドのパスでは、UID
0を拒否してください。起動元が root の場合は、確認済みの非 root の送信元 UID:GID を明示的に取得してください。出力ディレクトリの所有者から推測してはいけません。 --group-add <gid>— 共有データセットやワークスペースに対する、ホストの補助グループアクセスを維持します。標準的な配列では、プライマリ GID 以外のホストグループをすべて追加します。HOME、USER、LOGNAME、キャッシュのリダイレクト — ユーザーの上書き後に、フレームワークが/rootなどのイメージ所有の場所へ書き込むのを防ぎます。起動前に、書き込み可能なマウント上にこれらのディレクトリを準備してください。USER/LOGNAMEは見た目だけの設定ではなく、実際の動作に必要です。任意の--userUID はイメージ内の/etc/passwdに登録されていません。また、torch 2.x はインポート時にgetpass.getuser()を呼び出します(torch/_dynamo→ inductor のキャッシュディレクトリ設定)。どちらの環境変数も設定されていない場合、ワークロードコードの実行前に、コンテナはKeyError: 'getpwuid(): uid not found: <uid>'でクラッシュします。空でない名前であれば使えます。その名前がイメージ内に存在する必要はありません。-v host:container— バインドマウントです。コマンドではコンテナ側のパスのみを参照します。-e VAR— 親シェルから引き継ぎます(すでに設定済みであれば値は不要です)。シークレットにはこの形式を使用してください。
コンテナ名の衝突
docker run --name X は、X という名前のコンテナがすでに存在する場合に失敗します。名前を再利用する前に、次の防御的なパターンを使います。
docker stop my-worker 2>/dev/null; docker rm my-worker 2>/dev/null
docker run --name my-worker ...
デタッチと exec のパターン
同じコンテナで複数ステップのワークフロー(ダウンロード → 実行 → 後処理)を行う場合は、再起動のコストを避けます。
HOST_RESULTS=/host/results
HOST_UID="$(id -u)"
HOST_GID="$(id -g)"
[ "$HOST_UID" -ne 0 ] || { echo "Refusing writable Docker launch as UID 0" >&2; exit 1; }
HOST_IDENTITY_ARGS=(--user "$HOST_UID:$HOST_GID")
for group_id in $(id -G); do
[ "$group_id" = "$HOST_GID" ] || HOST_IDENTITY_ARGS+=(--group-add "$group_id")
done
mkdir -p "$HOST_RESULTS/.tao-runtime/home/.cache"/{huggingface,torch,triton,torchinductor,matplotlib}
docker run -d --name <worker> \
--gpus all --shm-size=8g \
"${HOST_IDENTITY_ARGS[@]}" \
-v <host-data>:/data \
-v "$HOST_RESULTS:/results" \
-e HOME=/results/.tao-runtime/home \
-e USER="$(id -un)" -e LOGNAME="$(id -un)" \
-e XDG_CACHE_HOME=/results/.tao-runtime/home/.cache \
-e HF_HOME=/results/.tao-runtime/home/.cache/huggingface \
-e TORCH_HOME=/results/.tao-runtime/home/.cache/torch \
-e TRITON_CACHE_DIR=/results/.tao-runtime/home/.cache/triton \
-e TORCHINDUCTOR_CACHE_DIR=/results/.tao-runtime/home/.cache/torchinductor \
-e MPLCONFIGDIR=/results/.tao-runtime/home/.cache/matplotlib \
--entrypoint sh \
<image> -c "tail -f /dev/null"
docker exec <worker> <step_1>
docker exec <worker> <step_2>
docker stop <worker> && docker rm <worker>
イメージがなければ取得する方法
docker image inspect <image> >/dev/null 2>&1 || docker pull <image>
コンテナ検索用のラベル
後からフィルタリングして一覧表示できるよう、コンテナにタグを付けます。
docker run --label tao-toolkit ...
docker ps --filter 'label=tao-toolkit'
マウントのパターン
コンテナは、イメージで定義された一般的なパス(多くの場合 /data、/results、/workspace/checkpoints)にデータがあることを想定します。ホスト側のパスは任意です。docker run 内のコマンドでは、コンテナ側のパスのみを参照します。
書き込み可能なマウントの所有権に関する不変条件
書き込み可能なバインドマウントでは、デフォルトで、実行時の UID:GID を投入元ホストのものにします。
ルートコンテナがより深い階層に 0755 ディレクトリを作成できる場合、マウントルートを事前に作成するだけでは不十分です。削除は親ディレクトリの権限で制御されるため、ホストユーザーはそのサブツリーにもアクセスできなくなります。
コンテナに対する --rm と docker rm が削除するのはコンテナの状態だけです。どちらもバインドマウントされたチェックポイントを削除したり、修復したりすることはありません。
イメージを root として実行してよいのは、ドキュメントまたは事前チェックによって、ホストユーザーでの実行に互換性がないと確認できた場合だけです。これを明示的な起動例外として扱ってください。書き込み可能な出力を分離し、すべての終了またはキャンセルの後、次の実験を開始する前に所有権を正規化してください。/bin/sh と chown があるイメージの場合、実行後の修復には次を使用します。
HOST_UID="$(id -u)"
HOST_GID="$(id -g)"
docker run --rm --user 0:0 --entrypoint /bin/sh \
-v /host/results:/owned-output \
<same-approved-image> \
-c 'chown -R "$1:$2" /owned-output' sh "$HOST_UID" "$HOST_GID"
すべての書き込み可能な出力/キャッシュマウントに修復を適用してください。エージェントが所有権の正規化を実行または検証できない場合、root が必要な例外を使ってはいけません。通常の修正方法として chmod 777 を代用してはいけません。
環境変数の規則
TAO スタイルのワークロードで共通して受け渡す変数(呼び出し元のスキルで必要なものを指定します):
NGC_KEY—nvcr.ioからのプルに使用します。一部のランタイムでは実行時にも読み取られますHF_TOKEN— アクセス制限付きの HuggingFace モデルのダウンロードに使用しますAWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_ENDPOINT_URL— コンテナ内での S3 I/O に使用しますWANDB_API_KEY— オプションの W&B ロギングに使用します
変数が親シェルにある場合は、-e VAR(=value なし)を使用してください。コマンドラインにシークレットを記載しないでください。
GPU を選択する別の方法として、--gpus の代わりに -e NVIDIA_VISIBLE_DEVICES=0,1(または all)と -e NVIDIA_DRIVER_CAPABILITIES=all を使用できます。標準的な x86 ホストでは --gpus フラグが推奨されます。環境変数を使う方法は古い方式であり、runtime=nvidia(Tegra/Jetson)ではこの方法が必要です。
コンテナの検査
docker ps # running containers only
docker ps -a # all containers, including exited
docker ps --filter status=running --format '{{.Names}} {{.Image}}'
docker logs <name_or_id> # stdout/stderr
docker logs -f <name_or_id> # follow (tail -f equivalent)
docker logs --tail 100 <name_or_id> # last N lines
docker inspect <name_or_id> # full config, mounts, env, network, state (JSON)
docker inspect --format '{{.State.Status}}' <name_or_id>
docker stats # live CPU/mem/network/block I/O
docker stats --no-stream # one snapshot, non-interactive
docker inspect は、コンテナのマウント、環境変数、コマンド、ネットワーク、終了コードに関する正式な信頼できる情報源です。コンテナが期待どおりに動作しない理由をデバッグする際に使用してください。
イメージの管理
docker pull <image>
docker image ls
docker system df # Docker-managed image/layer/volume usage
ホストごとに一度プルすれば、docker run はキャッシュされたイメージを再利用します。NVIDIA のイメージは通常 5~40GB です。
ディスクを分割している場合のデータルートの移動
一部のクラウド GPU プロバイダーでは、小さなルートボリュームと大きな一時ボリュームが提供されます。Docker はデフォルトで /var/lib/docker に書き込むため、ルートボリュームに大きなイメージを保存すると容量が不足します。次を確認してください。
df -h / # root volume size/free
lsblk # all block devices and mount points
/ の容量がイメージ全体のサイズより小さく、別の場所により大きなディスクがマウントされている場合は、イメージをプルする前に移動してください。
sudo systemctl stop docker
sudo mkdir -p <large_volume_path>/docker
sudo rsync -aP /var/lib/docker/ <large_volume_path>/docker/
sudo mv /var/lib/docker /var/lib/docker.old
sudo tee /etc/docker/daemon.json <<'EOF'
{ "data-root": "<large_volume_path>/docker" }
EOF
sudo systemctl start docker
docker info | grep 'Docker Root Dir'
sudo rm -rf /var/lib/docker.old
ネットワーク(複数コンテナのパターン)
名前で相互に通信するマイクロサービスコンテナの場合は、Docker ネットワークを作成し、コンテナを接続します。
docker network create tao-net
docker run --network tao-net --name api ...
docker run --network tao-net --name worker ... # can resolve `api` by name
ほとんどの TAO トレーニングワークロードでは、これは必要ありません。ジョブごとにコンテナは 1 つだけです。
よくあるエラーモード
could not select device driver "" with capabilities: [[gpu]] — NVIDIA Container Toolkit がインストールされていないか、Docker が NVIDIA ランタイム用に設定されていません。ユーザーの承認後、tao-setup-nvidia-gpu-host を --backend docker --install を付けて実行し(非対話型のエージェント実行では --yes を追加します)、その後 Docker を再起動してください。
docker pull での unauthorized: authentication required — NGC キーが無効か、設定されていません。docker login nvcr.io を再実行してください。
no space left on device — まず、どのファイルシステムとストレージクラスがいっぱいなのかを特定してください。バインドマウントされたトレーニング出力は docker system df にはカウントされず、Docker イメージのプルーニングでは解決しません。
df -h / /var/lib/docker <results_root>
docker system df
docker inspect <tao-container> --format '{{json .Mounts}}'
du -xhd1 <results_root> 2>/dev/null | sort -h
find <results_root> -maxdepth 3 -printf '%u:%g %m %s %p\n' 2>/dev/null | head
バインドマウントの場合は、確認済みの所有権修復を通じて、記録が終了状態にあるジョブのディレクトリ(tao_job_record.py get "$JOB_ID")だけを削除してください。docker system prune がこれらに影響すると決めつけないでください。Docker 自体のルートディレクトリの場合は、上記の説明に従って data-root を移動してください。docker system prune -a --volumes は破壊的な操作であり、ほかのワークフローに属する未使用のイメージやボリュームを削除する可能性があります。そのため、ユーザーの明示的な承認を得て、docker system df の内容を確認してから実行してください。
Bus error / DataLoader worker exited unexpectedly — /dev/shm の容量が不足しています。--shm-size を使って共有メモリを増やしてください(例:--shm-size=16g)。
バインドマウントされたパスでの permission denied — コンテナの UID とホストの UID が異なるか、HOME/フレームワークのキャッシュが引き続きイメージ所有のディレクトリを参照しています。上記の標準的なホスト UID:GID マッピングと、書き込み可能な HOME/キャッシュへのリダイレクトを使用してください。root 権限が必要と明記されたイメージの場合は、再試行する前に必須の実行後の所有権正規化を完了してください。
torch/torchvision のインポート時の KeyError: 'getpwuid(): uid not found: <uid>' — コンテナが、対応する /etc/passwd エントリも USER/LOGNAME 環境変数もない --user UID で実行されています。そのため、インポート時に getpass.getuser() が pwd.getpwuid() にフォールバックします。-e HOME=... だけでは解決しません。UID:GID マッピングを維持し、標準の ID 環境変数ブロック(-e USER=... -e LOGNAME=... +書き込み可能な HOME +キャッシュへのリダイレクト)を指定して起動してください。root で実行して回避しないでください。そうすると、出力が root 所有になる問題が再発します。
docker run -d の後の Error: No such container: <name> — 起動時にコンテナがクラッシュしました。docker ps -a で終了状態を確認し、原因は docker logs <name> で調べてください。デバッグ中は --rm を外してください。
対象範囲
このスキルは Docker 上で TAO ジョブを実行し(§ Execution)、ほかのスキルが参照する Docker の方法も説明します。関連項目:
tao-skill-bank:tao-run-on-brev— Brev インスタンスをプロビジョニングした後、コンテナの操作方法をこのスキルと同じ Docker コマンドに委ねます。tao-skill-bank:tao-launch-workflow— 受付/ルーティングの入口であり、このスキルが実装するプラットフォーム非依存の 4 コマンドの契約です。tao-skill-bank:tao-data-io— ストレージ階層の選択、ステージング、およびsubmitコマンドが呼び出すコンピュートフレームの検証ゲートです。
モデルスキルとデータスキルが仕様バンドル(何を)を作成し、このスキルがそれを実行します(どのように)。