docker入門 その4(Jupyter Notebook GPU版 立ち上げ)

その4である今回はDockerでJupyter Notebookのコンテナを立ち上げ、GPUを扱えるようにする手順について紹介します。

※注:こちらは2021年3月時点の手順である点、ご了承願います。DockerでGPUを扱うための手順はアップデートが早く、必ずしも本記事の内容が最新であることは保証していません。

本記事はGCP上にUbuntu20.04が乗ったVMインスタンスを前提としていますが、他の組み合わせでも参考になるかと思います。

GPUインスタンスの立ち上げ

GCP上でTerraformを使ってGPUインスタンスを立ち上げる手順はこちらです。

$ git clone https://github.com/bassbone/gcp-terraform.git -b v2
$ cd gcp-terraform
$ terraform init
$ terraform plan
$ terraform apply

こちらが無事完了するとTesla T4が付いたVMインスタンスが立ち上がります。

Docker、docker-composeのインストール

その1で触れていますので、こちらを参照ください。

NVIDIAドライバのインストール

ホスト側にNVIDIAドライバをインストールします。

$ lsmod | grep nouveau
# 何か表示された場合には作業が必要だが、今回試した環境では何も表示されなかった。

$ sudo add-apt-repository ppa:graphics-drivers/ppa
# 途中エンターキーの入力を求められたらエンターキーを

$ sudo apt update

# デバイスに対応するドライバーを確認するコマンドを実行するが、初期状態ではコマンドが無い場合が多い
$ ubuntu-drivers devices

Command 'ubuntu-drivers' not found, but can be installed with:

apt install ubuntu-drivers-common
Please ask your administrator.

$ sudo apt-get install -y ubuntu-drivers-common

# 改めて確認。特別な理由が無い限り、推奨のものでいいかと。
$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:04.0 ==
modalias : pci:v000010DEd00001EB8sv000010DEsd000012A2bc03sc02i00
vendor   : NVIDIA Corporation
model    : TU104GL [Tesla T4]
driver   : nvidia-driver-460 - distro non-free recommended
driver   : nvidia-driver-460-server - distro non-free
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-450 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

$ sudo apt-get install -y nvidia-driver-460

# 再起動は忘れずに
$ sudo reboot

# 無事にGPUが認識できるようになった。
$ nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.39       Driver Version: 460.39       CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            Off  | 00000000:00:04.0 Off |                    0 |
| N/A   58C    P8    10W /  70W |     70MiB / 15109MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A       957      G   /usr/lib/xorg/Xorg                 59MiB |
|    0   N/A  N/A      1103      G   /usr/bin/gnome-shell                9MiB |
+-----------------------------------------------------------------------------+

nvidia-container-runtimeのインストール

DockerとGPUをつなぐために「nvidia-container-runtime」なるものをインストールします。

こちらの手順を参考にインストールしました。

$ curl -s -L https://nvidia.github.io/nvidia-container-runtime/gpgkey | sudo apt-key add -
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
$ curl -s -L https://nvidia.github.io/nvidia-container-runtime/$distribution/nvidia-container-runtime.list | sudo tee /etc/apt/sources.list.d/nvidia-container-runtime.list

$ sudo apt-get update
$ sudo apt-get install -y nvidia-container-runtime

$ which nvidia-container-runtime-hook
/usr/bin/nvidia-container-runtime-hook

# Dockerの再起動を忘れずに
$ sudo systemctl restart docker

動作確認

コンテナからGPUを認識できるか試します。

$ sudo docker run -it --rm --gpus all ubuntu nvidia-smi
Thu Mar  4 16:23:50 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.39       Driver Version: 460.39       CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            Off  | 00000000:00:04.0 Off |                    0 |
| N/A   37C    P8     9W /  70W |    105MiB / 15109MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

無事DockerからGPUを認識することができました!

いよいよGPUが使えるJupyter Notebookを立ち上げていきます。

Dockerfileとdocker-compose.ymlの準備

今回作成するコンテナはnvidiaが提供するコンテナイメージをベースとします。(jupyteyのコンテナイメージをベースとして、nvidia関連の諸々をインストールしてしまうという手も無くはないですが)

FROM nvidia/cuda:11.0-devel-ubuntu20.04

RUN apt-get update
RUN apt-get install -y python3 python3-pip

RUN pip3 install jupyter
RUN pip3 install numpy pandas
RUN pip3 install torch torchvision

ENV LIBRARY_PATH /usr/local/cuda/lib64/stubs

ARG NB_USER="jovyan"
ARG NB_UID="1000"

RUN echo "auth requisite pam_deny.so" >> /etc/pam.d/su
RUN useradd -m -s /bin/bash -N -u $NB_UID $NB_USER

USER $NB_UID
RUN mkdir "/home/$NB_USER/work"

WORKDIR "/home/$NB_USER/work"

CMD ["jupyter", "notebook", "--ip=*", "--no-browser"]

docker-compose.ymlの書き方には2種類ありますので、両方とも紹介します。

書き方 その1

docker-compose.ymlはこちらです。

version: '3'
services:
  jupyter:
    build: .
    ports:
      - "8888:8888"
    volumes:
      - ./work:/home/jovyan/work
    runtime: nvidia

こちらの場合はruntimeの設定が必要ですので、以下を実行する必要があります。

# これを実行しないと[Unknown runtime specified nvidia]エラーが出る可能性があります。
$ sudo tee /etc/docker/daemon.json <<EOF
{
    "runtimes": {
        "nvidia": {
            "path": "/usr/bin/nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}
EOF

# Dockerの再起動を忘れずに
$ sudo systemctl restart docker

書き方 その2

docker-compose.ymlはこちらです。その1との違いはruntimeオプションでは無く、deployオプションを使っていることです。

version: '3'
services:
  jupyter:
    build: .
    ports:
      - "8888:8888"
    volumes:
      - ./work:/home/jovyan/work
    deploy:
      resources:
        reservations:
          devices:
          - driver: nvidia
            capabilities: [gpu]

書き方についてのまとめ

その1でもその2でも現在は動作しますが、その1の方が公式サイト上レガシーとなっています。その1の方がその2に比べて記載がシンプルですが、その2の方がGPUの割り当てを色々調整できてカスタマイズ性は高いようです。

Jupyter Notebook 立ち上げ

Dockerfileとdocker-compose.ymlを用意した上で、以下のコマンドを実行します。

$ sudo docker-compose build
$ sudo docker-compose up -d
$ sudo docker-compose ps
$ sudo docker-compose logs

SSHポートフォワーディングし、http://localhost:8888にアクセスすると、無事Jupyter Notebookが立ち上がり、さらにGPUが使えることも確認できました!

終わりに

今回紹介した手順が2021年3月時点での最新のものでは無いかと思います!

しかし、冒頭でも触れたように日々アップデートされていくので、この辺りの情報は常にチェックしておいて、アップデートがあり次第、記事化しきたいです。