Help us understand the problem. What is going on with this article?

nvidia-docker in nvidia-dockerを実現する

More than 1 year has passed since last update.

2行まとめ

  • 「nvidia-docker in nvidia-docker」は可能。
  • nvidia-dockerはバージョン1.0系とバージョン2.0系があり、2.0系の方がいろいろと楽。

概要

例えばCI(Continuous Integration、継続的インテグレーション)環境としてJenkinsのコンテナを動作させており、その中からDockerコンテナを起動したい場合、いわゆる「Docker in Docker」を実現することになります。
また、NVIDIA製GPUをDockerコンテナ内から使いたい場合、nvidia-dockerを使うのが一般的かと思います。
これらを組み合わせて「nvidia-docker in nvidia-docker」を実現するのがこの記事の目的です。

なお、CI環境などの開発環境を想定しているため、セキュリティについては十分に考慮していません。/var/run/docker.sockのマウントなどは十分に注意して行ってください。

まずは「Docker in Docker」

まずはnvidia-dockerのことは忘れて、普通のDockerコンテナ内からdockerコマンドを起動してみましょう。
なお、環境は以下の通りです。

yuya@host$ uname -a
Linux xxx 4.4.0-119-generic #143-Ubuntu SMP Mon Apr 2 16:08:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

yuya@host$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.4 LTS"

yuya@host$ docker version
Client:
 Version:       17.12.1-ce
 API version:   1.35
 Go version:    go1.9.4
 Git commit:    7390fc6
 Built: Tue Feb 27 22:17:40 2018
 OS/Arch:       linux/amd64

Server:
 Engine:
  Version:      17.12.1-ce
  API version:  1.35 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   7390fc6
  Built:        Tue Feb 27 22:16:13 2018
  OS/Arch:      linux/amd64
  Experimental: false

Dockerコンテナ内でdocker versionを実行する例は以下の通りです。Dockerデーモンに正しく接続できていることが確認できます。

yuya@host$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
Digest: sha256:9ee3b83bcaa383e5e3b657f042f4034c92cdd50c03f73166c145c9ceaea9ba7c
Status: Image is up to date for ubuntu:16.04

yuya@host$ docker run --interactive --tty --rm \
  --volume /usr/bin/docker:/usr/bin/docker:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --group-add $(stat --format "%g" /var/run/docker.sock) \
  ubuntu:16.04 \
  /bin/bash

root@container# id
uid=0(root) gid=0(root) groups=0(root),130

root@container# apt-get update && apt-get install --yes --no-install-recommends libltdl7

root@container# docker version
Client:
 Version:       17.12.1-ce
 API version:   1.35
 Go version:    go1.9.4
 Git commit:    7390fc6
 Built: Tue Feb 27 22:17:40 2018
 OS/Arch:       linux/amd64

Server:
 Engine:
  Version:      17.12.1-ce
  API version:  1.35 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   7390fc6
  Built:        Tue Feb 27 22:16:13 2018
  OS/Arch:      linux/amd64
  Experimental: false

それぞれのオプションの意味は以下の通りです。

  • --volume /usr/bin/docker:/usr/bin/docker:ro
    • Dockerホスト側の/usr/bin/dockerdockerコマンド自体)をDockerコンテナ側に読み取り専用でマウントします。
    • dockerコマンドはGo言語で開発されており、依存関係が少ないため、このようにコマンドをコピーするという乱暴な方法でも動作します。
  • --volume /var/run/docker.sock:/var/run/docker.sock
    • Dockerデーモンに接続するためのUNIXソケットをマウントします。
  • --group-add $(stat --format "%g" /var/run/docker.sock):
    • Dockerコンテナ内の実行ユーザに/var/run/docker.sockへの権限を与えます。
    • Dockerコンテナ内でrootユーザを使う場合は不要ですが、それ以外のユーザで実行する場合は必要です。

libltdl7パッケージをインストールしているのは、ubuntu:16.04イメージではdockerコマンドの実行に必要なライブラリが足りないためです。インストールせずにdocker versionコマンドを実行すると、以下のエラーメッセージが表示されます。

root@container# docker version
docker: error while loading shared libraries: libltdl.so.7: cannot open shared object file: No such file or directory

nvidia-docker in nvidia-docker(バージョン1.0系)

バージョン1.0系のnvidia-dockerでは、nvidia-dockerコマンドを使います。今回は以下の環境で検証しました。

yuya@host$ dpkg -l | grep nvidia-docker
ii  nvidia-docker    1.0.1-1    amd64    NVIDIA Docker container tools

バージョン1.0系における「nvidia-docker in nvidia-docker」の例は以下の通りです。nvidia-smiが正しく実行できていることが確認できます。

yuya@host$ docker pull nvidia/cuda:latest
latest: Pulling from nvidia/cuda
Digest: sha256:74570aef804e30486eb74b284fd3091d14ca7144736c44fb48c13e5e6afb963f
Status: Image is up to date for nvidia/cuda:latest

yuya@host$ nvidia-docker run --interactive --tty --rm \
  --volume /usr/bin/docker:/usr/bin/docker:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume /usr/bin/nvidia-docker:/usr/bin/nvidia-docker:ro \
  --group-add $(stat --format "%g" /var/run/docker.sock) \
  nvidia/cuda:latest \
  /bin/bash

root@container# id
uid=0(root) gid=0(root) groups=0(root),130

root@container# apt-get update && apt-get install --yes --no-install-recommends libltdl7 nvidia-modprobe

root@container# nvidia-docker version
NVIDIA Docker: 1.0.1

Client:
 Version:       17.12.1-ce
 API version:   1.35
 Go version:    go1.9.4
 Git commit:    7390fc6
 Built: Tue Feb 27 22:17:40 2018
 OS/Arch:       linux/amd64

Server:
 Engine:
  Version:      17.12.1-ce
  API version:  1.35 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   7390fc6
  Built:        Tue Feb 27 22:16:13 2018
  OS/Arch:      linux/amd64
  Experimental: false

root@container# nvidia-smi
Mon Apr 16 09:06:38 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 387.34                 Driver Version: 387.34                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1080    Off  | 00000000:02:00.0  On |                  N/A |
| 33%   49C    P2    37W / 180W |   3166MiB /  8111MiB |     10%      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 1080    Off  | 00000000:03:00.0 Off |                  N/A |
| 27%   39C    P8     5W / 180W |     27MiB /  8114MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

root@container# nvidia-docker run --interactive --tty --rm nvidia/cuda:latest nvidia-smi
Mon Apr 16 09:06:58 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 387.34                 Driver Version: 387.34                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 1080    Off  | 00000000:02:00.0  On |                  N/A |
| 33%   49C    P2    37W / 180W |   3166MiB /  8111MiB |     10%      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 1080    Off  | 00000000:03:00.0 Off |                  N/A |
| 27%   39C    P8     5W / 180W |     27MiB /  8114MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

なお、nvidia-modprobeパッケージをインストールしていない場合、nvidia-docker時に以下のエラーが発生します。

root@container# nvidia-docker run --interactive --tty --rm nvidia/cuda:latest nvidia-smi
nvidia-docker | 2018/04/16 09:31:10 Error: Could not load UVM kernel module. Is nvidia-modprobe installed?

nvidia-docker in nvidia-docker(バージョン2.0系)

バージョン2.0系のnvidia-dockerでは、普段通りdockerコマンドを使います。今回は以下の環境で検証しました。

yuya@host$ dpkg -l | grep nvidia-docker
ii  nvidia-docker2    2.0.2+docker17.12.0-1    all    nvidia-docker CLI wrapper

バージョン2.0系における「nvidia-docker in nvidia-docker」の例は以下の通りです。nvidia-smiが正しく実行できていることが確認できます。

yuya@host$ docker pull nvidia/cuda:latest
latest: Pulling from nvidia/cuda
Digest: sha256:74570aef804e30486eb74b284fd3091d14ca7144736c44fb48c13e5e6afb963f
Status: Image is up to date for nvidia/cuda:latest

yuya@host$ docker run --interactive --tty --rm \
  --runtime nvidia \
  --volume /usr/bin/docker:/usr/bin/docker:ro \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --group-add $(stat --format "%g" /var/run/docker.sock) \
  nvidia/cuda:latest \
  /bin/bash

root@container# id
uid=0(root) gid=0(root) groups=0(root),999

root@container# apt-get update && apt-get install --yes --no-install-recommends libltdl7

root@container# docker version
Client:
 Version:       17.12.0-ce
 API version:   1.35
 Go version:    go1.9.2
 Git commit:    c97c6d6
 Built: Wed Dec 27 20:11:19 2017
 OS/Arch:       linux/amd64

Server:
 Engine:
  Version:      17.12.0-ce
  API version:  1.35 (minimum version 1.12)
  Go version:   go1.9.2
  Git commit:   c97c6d6
  Built:        Wed Dec 27 20:09:53 2017
  OS/Arch:      linux/amd64
  Experimental: false

root@container# nvidia-smi
Mon Apr 16 09:08:41 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 387.34                 Driver Version: 387.34                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 108...  Off  | 00000000:03:00.0  On |                  N/A |
|  0%   44C    P2    93W / 280W |   1786MiB / 11169MiB |     45%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

root@container# docker run --interactive --tty --rm --runtime nvidia nvidia/cuda:latest nvidia-smi
Mon Apr 16 09:08:58 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 387.34                 Driver Version: 387.34                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 108...  Off  | 00000000:03:00.0  On |                  N/A |
|  0%   46C    P2    83W / 280W |   1786MiB / 11169MiB |     30%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

参考

yuyakato
株式会社那由多屋の代表取締役社長です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした