AI実習環境やGPUサーバーを構築する際、このようなコマンドを頻繁に見かけることになります。
docker run --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
あるいは、Kubernetes環境では、GPUノードにNVIDIAドライバーをインストールし、NVIDIA Container Toolkitを構成した後、GPUが必要なコンテナを実行します。
ここで自然とこのような疑問が生まれます。
「コンテナは本来隔離された環境なのに、どのようにホストサーバーのGPUを使用できるのだろうか?」
この疑問に対する答えが、NVIDIA Container Toolkitのアーキテクチャです。
NVIDIA Container Toolkitは、Docker、containerd、CRI-O、LXCといった様々なコンテナランタイムでNVIDIA GPUを使用できるように支援するコンポーネントの集合体です。NVIDIAの公式ドキュメントでも、NVIDIAコンテナスタックは特定のランタイム一つに縛られず、エコシステムの複数のコンテナランタイムをサポートできるように設計されていると説明されています。

1. なぜNVIDIA Container Toolkitが必要なのか?
コンテナは基本的にホストと隔離された実行環境です。そのため、コンテナ内でGPUを使用するには、単にCUDAイメージを一つ実行するだけでは完結しません。
GPUを使用するには、おおよそ以下の要素が必要です。
第一に、ホストOSにNVIDIA GPUドライバーがインストールされている必要があります。
第二に、コンテナ内で/dev/nvidia*のようなGPUデバイスファイルにアクセスできる必要があります。
第三に、コンテナ内でNVIDIAドライバー関連のライブラリと実行ファイルを使用できる必要があります。
第四に、Docker、containerd、CRI-Oのようなコンテナランタイムが「このコンテナにはGPUを接続する必要がある」という情報を理解している必要があります。
つまり、GPUコンテナの実行は、単にコンテナイメージだけの問題ではありません。ホストのGPUデバイス、ドライバー、ライブラリ、コンテナランタイム設定が連携して動作する必要があります。
NVIDIA Container Toolkitは、このプロセスを自動化し、標準化するツールです。
簡単に言えば、以下のようになります。
NVIDIA Container Toolkitは、コンテナがホストのNVIDIA GPUを安全かつ一貫した方法で使用できるように、デバイスファイル、ドライバーライブラリ、ランタイム設定を接続するレイヤーである。
2. NVIDIAコンテナスタックの全体構造
NVIDIA公式ドキュメントで説明されているNVIDIAコンテナスタックの主要な構成要素は、大きく分けて3つです。
| 構成要素 | 代表コマンド/パッケージ | 役割 |
|---|---|---|
| NVIDIA Container Runtime | nvidia-container-runtime | Docker/containerdのようなランタイムとrunCの間でNVIDIA設定を注入 |
| NVIDIA Container Runtime Hook | nvidia-container-toolkit, nvidia-container-runtime-hook | コンテナ開始直前にGPUデバイスとライブラリ注入作業を実行 |
| NVIDIA Container Library and CLI | libnvidia-container1, nvidia-container-cli | 実際のGPUデバイス、ドライバーライブラリ、マウント構成を処理 |
これらの構成要素は個別に存在しますが、一般ユーザーは通常nvidia-container-toolkitパッケージをインストールして使用します。NVIDIAドキュメントでも、すべての使用事例においてnvidia-container-toolkitパッケージのインストールだけで十分であると説明されています。
3. まず全体フローを理解する
Dockerを基準に、コンテナがGPUを使用するフローを単純化すると以下のようになります。
사용자
↓
docker run --gpus all ...
↓
Docker daemon
↓
nvidia-container-runtime
↓
runC spec 수정
↓
NVIDIA prestart hook 추가
↓
runC 실행
↓
nvidia-container-cli 호출
↓
GPU 장치와 라이브러리 컨테이너에 주입
↓
컨테이너 내부에서 nvidia-smi 실행 가능

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/arch-overview.html
ここでの核心は、nvidia-container-runtimeが直接コンテナを完全に実行する独立したランタイムというよりも、既存のrunCの前段でNVIDIA関連の設定を挿入する役割を果たすという点です。
NVIDIAドキュメントによると、nvidia-container-runtimeは過去にはrunCをフォークした構造でしたが、2019年以降はホストにインストールされたネイティブなrunCをラップする薄いラッパーとして動作します。このランタイムはrunCのspecを入力として受け取り、NVIDIA Container Runtime Hookをprestart hookとして追加した後、修正されたspecをネイティブなrunCに渡します。
4. 最下層: libnvidia-containerとnvidia-container-cli
NVIDIAコンテナスタックの最下層にある主要な構成要素がlibnvidia-containerとnvidia-container-cliです。
公式ドキュメントでは、これらの構成要素がGNU/LinuxコンテナがNVIDIA GPUを使用できるように自動構成するライブラリとCLIであり、実装はLinuxカーネルプリミティブに基づいており、特定のコンテナランタイムに依存しないように設計されていると説明されています。
簡単に言えば、このレイヤーは実際の作業担当者です。
例えば、コンテナ内に以下のようなものを接続する必要があります。
/dev/nvidia0
/dev/nvidiactl
/dev/nvidia-uvm
NVIDIA driver library
CUDA 관련 runtime library
GPU capabilities 정보
このとき、「どのGPUを入れるか」、「どのライブラリをマウントするか」、「コンテナ内でどのようなパスとして見せるか」といった作業を処理する主要なツールがnvidia-container-cliです。
つまり、コンテナランタイムが直接NVIDIA GPUの詳細な構成をすべて知っているのではなく、NVIDIAが提供するnvidia-container-cliを呼び出してGPUサポートを注入する構造です。
5. 中間層: NVIDIA Container Runtime Hook
次に重要な構成要素がNVIDIA Container Runtime Hookです。
公式ドキュメントによると、このフックはrunCのprestart hookインターフェースを実装した実行ファイルです。runCがコンテナを作成した後、まだコンテナプロセスを開始する前にこのフックが呼び出されます。このとき、フックはコンテナのconfig.json情報を読み取り、適切なフラグとともにnvidia-container-cliを呼び出します。特に、どのGPUデバイスをコンテナに注入するかが重要なフラグの一つです。
この説明をもう少し簡単にすると以下のようになります。
コンテナ実行過程には、「コンテナは作成されたがまだ開始されていない瞬間」があります。
まさにこの時点が重要です。
コンテナがすでに開始された後にGPUデバイスとライブラリを無理やり入れるのではなく、コンテナ開始直前に必要なGPU設定を事前に注入します。
そのため、prestart hookという名前が付けられています。
컨테이너 생성
↓
아직 애플리케이션 실행 전
↓
NVIDIA prestart hook 실행
↓
GPU 장치와 라이브러리 주입
↓
컨테이너 애플리케이션 시작
この構造のおかげで、コンテナ内部のアプリケーションは、まるでGPUが元々コンテナ内にあるかのように使用できます。
6. 上位層: NVIDIA Container Runtime
Dockerやcontainerd環境では、nvidia-container-runtimeがOCI-compliant runtimeとして設定されます。NVIDIAドキュメントでも、Dockerまたはcontainerdを使用する際にはNVIDIA Container RuntimeがOCI-compliant runtimeとして構成されると説明されています。
ここでOCIはOpen Container Initiativeを意味します。コンテナイメージとランタイムの動作方式に関する標準を定義するエコシステムです。
Dockerを実行するからといって、Dockerが単独で全ての処理を行うわけではありません。Dockerは内部的にcontainerd、runCのようなレイヤーと連携して動作します。
単純化すると以下のようになります。
Docker CLI
↓
Docker daemon
↓
containerd
↓
OCI runtime
↓
runC
↓
Linux namespace / cgroup 기반 컨테이너 실행
NVIDIA Container Runtimeは、このフローのOCI runtime段階に介入します。
ユーザーがGPUコンテナを実行すると、NVIDIA Container RuntimeがrunC specを修正し、NVIDIA hookを追加した後、実際のコンテナ実行はネイティブなrunCに任せます。
この構造を理解することで、nvidia-container-runtimeという名前から生じる可能性のある誤解を減らすことができます。
nvidia-container-runtimeはDocker自体を置き換えるものではありません。また、runC全体を置き換えるものでもありません。現在の構造では、既存のrunCの前でNVIDIA GPU設定を注入するラッパーに近いものです。
7. Docker/containerdとCRI-O/LXCの違い
NVIDIA Container Toolkitは、コンテナランタイムの種類によって使用されるフローが異なります。
公式ドキュメントでは、Dockerまたはcontainerdの場合、nvidia-container-runtimeがOCI-compliant runtimeとして構成されると説明されています。一方、CRI-OとLXCのフローでは、NVIDIA Container Runtimeコンポーネントは必要ないと説明されています。
この違いを簡単にまとめると以下のようになります。
| ランタイム | 主要フロー | 特徴 |
|---|---|---|
| Docker | Docker → NVIDIA Container Runtime → runC → NVIDIA Hook | DockerにNVIDIAランタイムを登録して使用 |
| containerd | containerd → NVIDIA Container Runtime → runC → NVIDIA Hook | Kubernetesノードで頻繁に使用 |
| CRI-O | CRI-O → NVIDIA Hook/CLIレイヤー | 別途NVIDIA Container Runtimeは不要な場合がある |
| LXC | LXC → NVIDIA Hook/CLIレイヤー | Docker系とはフローが異なる |
| Podman | CDI使用推奨 | 最近ではCDI方式が重要 |
つまり、NVIDIA Container Toolkitは一つの方式だけを強制するものではありません。コンテナランタイムの構造によってGPUを注入する経路が異なります。
8. パッケージ構造を理解する
NVIDIA Container Toolkitの主要なパッケージは以下の通りです。
nvidia-container-toolkit
nvidia-container-toolkit-base
libnvidia-container-tools
libnvidia-container1
パッケージの依存関係はおおよそ以下の通りです。
nvidia-container-toolkit
├─ libnvidia-container-tools
│ └─ libnvidia-container1
└─ nvidia-container-toolkit-base
libnvidia-container-tools
└─ libnvidia-container1
libnvidia-container1
各パッケージを役割中心に見ると以下のようになります。
| パッケージ | 役割 |
|---|---|
| libnvidia-container1 | NVIDIA GPUコンテナサポートのためのコアライブラリ |
| libnvidia-container-tools | nvidia-container-cliなどのCLIツールを提供 |
| nvidia-container-toolkit-base | nvidia-container-runtime、nvidia-ctkなどの基本ツールを含む |
| nvidia-container-toolkit | 一般的にインストールされる統合パッケージ |
実務では、パッケージを一つ一つ分けてインストールするよりも、ほとんどの場合nvidia-container-toolkitをインストールすれば十分です。

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/arch-overview.html
公式ドキュメントも、すべての使用事例においてnvidia-container-toolkitのインストールで十分であると説明しています。
9. nvidia-docker2とは今や何なのか?
以前の資料を見ると、nvidia-docker2というパッケージを頻繁に見かけることがあります。
過去には、NVIDIA GPUをDockerで使用するにはnvidia-docker2をインストールするようにというドキュメントが多くありました。そのため、今でも古いブログやインストールガイドにはnvidia-docker2が登場します。
しかし、現在のNVIDIA公式ドキュメントでは、nvidia-docker2とnvidia-container-runtimeパッケージは非推奨と見なすべきだと説明しています。その機能がnvidia-container-toolkitパッケージに統合されたためです。ただし、古いワークフローとの互換性のために、パッケージが引き続き提供される可能性はあります。
まとめると以下のようになります。
과거 방식:
nvidia-docker2 중심
현재 권장 방식:
nvidia-container-toolkit 중심
したがって、新しい環境を構成する場合は、nvidia-docker2を基準にするよりも、nvidia-container-toolkitとnvidia-ctkを基準に考えるのが良いでしょう。
10. nvidia-ctkとはどのようなツールか?
nvidia-ctkはNVIDIA Container Toolkit CLIです。
公式ドキュメントでは、このCLIがDockerのようなランタイムをNVIDIA Container Toolkitと連携して使用できるように設定したり、CDI仕様を生成したりする機能を含むと説明されています。
例えば、DockerでNVIDIAランタイムを使用するように設定するには、次のコマンドを使用できます。
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
NVIDIAのインストールドキュメントによると、このコマンドはホストの/etc/docker/daemon.jsonファイルを修正し、DockerがNVIDIA Container Runtimeを使用できるように更新します。
containerdをKubernetes用に構成する際には、次のようなコマンドを使用できます。
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
公式ドキュメントによると、containerdの場合、nvidia-ctkは基本的に/etc/containerd/conf.d/99-nvidia.tomlというドロップイン設定ファイルを作成し、/etc/containerd/config.tomlのimports設定を更新します。
つまり、nvidia-ctkは、人が直接設定ファイルを開いて複雑に修正する必要がある作業を代行してくれる管理ツールだと考えられます。
11. Kubernetesではどのように理解すべきか?
KubernetesでGPUを使用する場合、一般的にノードレベルで次の構成が必要です。
GPU가 장착된 노드
↓
NVIDIA GPU Driver 설치
↓
NVIDIA Container Toolkit 설치
↓
containerd 또는 Docker 런타임 구성
↓
NVIDIA Device Plugin 배포
↓
Pod에서 nvidia.com/gpu 리소스 요청
ここでNVIDIA Container Toolkitは、「コンテナランタイムが実際にGPUをコンテナに接続できるようにする基盤レイヤー」です。
Kubernetesスケジューラーの立場からは、GPUリソースがあるノードにPodを配置する必要があります。しかし、Podが実際にGPUデバイスをコンテナ内で使用できるようにするには、コンテナランタイムがGPUデバイスとライブラリを注入できる必要があります。
このときNVIDIA Container Toolkitが必要です。
例えば、Podスペックでは次のようにGPUリソースを要求できます。
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: Never
containers:
- name: cuda
image: nvidia/cuda:12.4.1-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
このYAMLだけではGPUが自動的に有効になるわけではありません。
ノードにNVIDIAドライバーがインストールされている必要があり、コンテナランタイムがNVIDIA Container Toolkitを通じてGPUを注入できる必要があり、KubernetesがGPUリソースを認識できるようにDevice Pluginも構成されている必要があります。
12. CDI(Container Device Interface)はなぜ重要になったのか?
最近では、CDI(Container Device Interface)も重要になっています。
NVIDIAドキュメントによると、NVIDIA Container Toolkitはv1.12.0からCDI specificationの生成をサポートしています。CDIは、NVIDIA GPUのようなデバイスにアクセスすることが何を意味するのかを抽象化し、複数のコンテナランタイムでデバイスアクセス方式を標準化するためのオープン仕様です。
簡単に言えば、CDIは「コンテナでGPUのようなデバイスを表現する標準仕様」です。
既存の方式では、特定のランタイムフックや環境変数に依存する部分が大きかったです。CDIを使用すると、GPUデバイスをより標準化された方法でコンテナランタイムに渡すことができます。
特にPodmanのような環境では、NVIDIAはCDIの使用を推奨しています。NVIDIAのインストールドキュメントでも、Podmanの場合、NVIDIAデバイスアクセスにCDIの使用を推奨すると説明されています。
例えば、Podmanでは次のようにCDIデバイスを指定できます。
podman run --rm
--device nvidia.com/gpu=all
--security-opt=label=disable
ubuntu nvidia-smi -L
NVIDIAドキュメントでは、このコマンドがホストでnvidia-smi -Lを実行したときと同じGPUリストを表示するはずだと説明されています。
また、NVIDIA Container Toolkit v1.18.0からは、nvidia-cdi-refreshというsystemdサービスがCDI specificationを自動的に生成および更新します。このサービスは、Toolkitのインストール/アップグレード、GPUドライバーのインストール/アップグレード、システム再起動時に/var/run/cdi/nvidia.yamlを作成または更新します。
13. DockerにおけるGPUコンテナ実行フローの例
Dockerを基準に、ユーザーが次のコマンドを実行すると仮定してみましょう。
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
このコマンドが実行されるとき、内部的にはおおよそこのようなことが起こります。
1. 사용자가 Docker CLI로 GPU 사용을 요청한다.
2. Docker daemon이 컨테이너 생성을 준비한다.
3. NVIDIA Container Runtime이 OCI runtime spec을 수정한다.
4. prestart hook에 NVIDIA Container Runtime Hook이 추가된다.
5. runC가 컨테이너 생성 후 시작 직전에 hook을 실행한다.
6. hook이 nvidia-container-cli를 호출한다.
7. nvidia-container-cli가 GPU 장치와 필요한 라이브러리를 컨테이너에 주입한다.
8. 컨테이너 내부에서 nvidia-smi가 GPU를 인식한다.
この構造で重要な点は、コンテナイメージの中にGPUドライバー全体をインストールする方式ではないということです。
ホストにインストールされたNVIDIAドライバーとGPUデバイスをコンテナが使用できるように接続してあげる方式です。
そのため、GPUコンテナ環境では次の順序が重要です。
호스트 NVIDIA 드라이버 정상 동작 확인
↓
nvidia-smi 확인
↓
NVIDIA Container Toolkit 설치
↓
Docker/containerd 런타임 설정
↓
GPU 컨테이너 실행 테스트
14. インストールと構成フロー
NVIDIA Container Toolkitのインストールドキュメントによると、最初に必要なのはLinuxディストリビューションに合ったNVIDIA GPUドライバーのインストールです。NVIDIAは、ディストリビューションのパッケージマネージャーを使用したドライバーのインストールを推奨すると説明しています。
Ubuntu/Debian系では、NVIDIAリポジトリを登録した後、Toolkitパッケージをインストールします。公式ドキュメントには、aptベースのインストール例とともに、nvidia-container-toolkit、nvidia-container-toolkit-base、libnvidia-container-tools、libnvidia-container1パッケージのインストール例が提供されています。
インストール後、Dockerを構成する代表的なフローは以下の通りです。
# DockerがNVIDIA Container Runtimeを使用できるように設定
sudo nvidia-ctk runtime configure --runtime=docker
# Dockerを再起動
sudo systemctl restart docker
# GPUコンテナをテスト
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
Kubernetesでcontainerdを使用する場合には、次のフローを考えればよいでしょう。
# containerdがNVIDIA Container Runtimeを使用できるように設定
sudo nvidia-ctk runtime configure --runtime=containerd
# containerdを再起動
sudo systemctl restart containerd
その後、KubernetesではNVIDIA Device Pluginをデプロイし、Podでnvidia.com/gpuリソースを要求する方式でGPUワークロードを実行します。
15. 実務でよく混同される点
15.1 コンテナ内にNVIDIAドライバーをインストールする必要があるか?
一般的に、コンテナイメージの中にホスト用のNVIDIAドライバーをインストールする方式でアプローチすることはありません。
GPUドライバーはホストカーネルと連携して動作します。コンテナはホストのGPUデバイスとドライバーライブラリを使用できるように構成されます。
コンテナイメージはCUDA runtime、cuDNN、アプリケーションコードなどを含むことができますが、実際のGPUデバイスとカーネルドライバーはホスト側が重要です。
15.2 nvidia-smiがホストでは動作するがコンテナでは動作しない場合?
この場合、以下を確認する必要があります。
# ホストでGPU認識を確認
nvidia-smi
# NVIDIA Container Toolkitのインストール状況を確認
dpkg -l | grep nvidia-container
# または
rpm -qa | grep nvidia-container
# Dockerランタイム設定を確認
cat /etc/docker/daemon.json
# containerd設定を確認
cat /etc/containerd/config.toml
ls -al /etc/containerd/conf.d/
Docker環境であれば、次のコマンドでランタイム構成を再適用できます。
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
containerd環境であれば、次のコマンドを使用できます。
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
15.3 nvidia-docker2をインストールする必要があるか?
新しい環境であれば、一般的にnvidia-docker2よりもnvidia-container-toolkitを基準にアプローチするのが良いでしょう。
公式ドキュメントでは、nvidia-docker2とnvidia-container-runtimeパッケージは非推奨と説明されており、その機能はnvidia-container-toolkitに統合されています。
15.4 AWS GPUインスタンスイメージにnvidia-ctkがなぜインストールされているのか?
AWSのGPUベースイメージやAI/ML用イメージには、NVIDIAドライバー、CUDA、コンテナ実行環境が事前に構成されていることが多いです。
このようなイメージにnvidia-ctkがインストールされている場合、コンテナでGPUを使用できるようにDockerやcontainerdを簡単に構成するための目的だと考えられます。
特にOllama、vLLM、PyTorch、TensorFlowのようなワークロードをコンテナで実行するには、GPUデバイスがコンテナに正常に伝達される必要があります。このときNVIDIA Container Toolkitとnvidia-ctkが重要な役割を果たします。
16. 一枚でまとめるアーキテクチャ
全体構造を一度にまとめると以下のようになります。
[사용자 명령]
docker run --gpus all ...
│
▼
[Docker / containerd]
컨테이너 생성 요청 처리
│
▼
[nvidia-container-runtime]
OCI runtime spec 수정
NVIDIA prestart hook 추가
│
▼
[runC]
컨테이너 생성
prestart hook 실행
│
▼
[nvidia-container-runtime-hook]
config.json 분석
nvidia-container-cli 호출
│
▼
[nvidia-container-cli / libnvidia-container]
GPU 장치 파일 주입
드라이버 라이브러리 마운트
환경 구성
│
▼
[컨테이너]
nvidia-smi
CUDA 애플리케이션
AI 모델 추론/학습
このフローを理解すれば、GPUコンテナの問題をはるかに簡単にデバッグできます。
例えば、問題が発生したとき、次のようにレイヤーを分けて見ることができます。
1. 호스트 GPU 문제인가?
- nvidia-smi가 호스트에서 동작하는가?
2. Toolkit 설치 문제인가?
- nvidia-container-toolkit 패키지가 설치되어 있는가?
3. 런타임 설정 문제인가?
- Docker/containerd가 NVIDIA runtime을 사용하도록 구성되어 있는가?
4. 컨테이너 실행 옵션 문제인가?
- docker run --gpus all 옵션을 사용했는가?
- Kubernetes Pod에서 nvidia.com/gpu 리소스를 요청했는가?
5. 애플리케이션 문제인가?
- CUDA 버전, 프레임워크 버전, 드라이버 호환성이 맞는가?
17. 結論
NVIDIA Container Toolkitは単なる「GPUコンテナ実行ツール」ではありません。
より正確に言えば、コンテナランタイムとNVIDIA GPUの間を接続する標準化された構成レイヤーです。
Dockerやcontainerdでは、NVIDIA Container RuntimeがOCI runtimeフローに組み込まれ、runC prestart hookを通じてnvidia-container-cliが呼び出されます。CRI-OやLXCではフローが異なる場合があり、最近ではCDIを通じたデバイスの標準化も重要になっています。
実務的に覚えておくべき核心は次の三つです。
- 第一に、GPUドライバーはホストにインストールされている必要があります。
- 第二に、コンテナランタイムはNVIDIA Container Toolkitを通じてGPUデバイスとライブラリをコンテナに注入する必要があります。
- 第三に、新しい環境ではnvidia-docker2よりもnvidia-container-toolkitとnvidia-ctkを中心に理解するのが良いでしょう。
AIインフラ、GPUサーバー、Kubernetes GPUノード、Ollama/vLLMのようなLLM推論環境を構成するのであれば、NVIDIA Container Toolkitアーキテクチャは必ず理解しておくべき基盤知識です。
この構造を理解すれば、「なぜホストではGPUが見えるのにコンテナでは見えないのか」、「なぜDocker daemon.jsonを修正する必要があるのか」、「なぜcontainerdの再起動が必要なのか」、「なぜKubernetes GPU PodがPendingまたは実行失敗状態になるのか」をはるかに体系的に分析できるようになります。
##
参考資料:
コメントを残す