GPGPU
GPU
docker
nvidia-docker
nvidia-docker2

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

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      |
|=============================================================================|
+-----------------------------------------------------------------------------+

参考