サーバ開発で当たり前のように使われるコンテナ技術(Docker等)ですが、GPUが絡んでくると最初の設定でつまづくことが多々あります。ここでは、こうやったらできたというのをメモとして残しておきたいと思います。
ホスト側のGPU設定
コンテナを作る前に、そのコンテナが動くホストのGPUが使える状態になっていないと、当然コンテナでも使えません。なので、まず初めにホスト側のGPUが使えるかの確認です。ホストOSはubuntuを前提に書きます。
GPUが使えるかどうかは、nvidia-smiコマンドで確認できます。これで、GPUの使用率などが表示されたら使える状態です。nvidia-smiコマンドが見つからない場合は、/usr/local/cuda等を探してみましょう。それでも入ってなさそうな場合は、cudaをインストールする必要があります。
CUDAのインストールは、ubuntu20.04の場合、
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get -y install cuda
と、1行ずつ実行すればインストールできます。
nvidia-smiコマンドもインストールされていると思います。nvidia-smiコマンドでGPUの情報が見られればOKです。
AWSのGPUインスタンスを使う場合は、AWSから提供されているDeepLearning Base AMI (ubuntu20.04)を使うと楽です。
GPUのDockerコンテナ作成
GPU対応のDockerコンテナを作成する場合、元となるイメージも普通のubuntuイメージではなく、nvidia/cudaのイメージを使う必要があります。
こちらのDocker Hubで、nvidia/cudaのイメージリストがありますので、この中から選んで docker pullすることでイメージをダウンロードでき、イメージからコンテナを作成できます。
作成したコンテナの中に入り、GPUが使えるように設定していきます。
まず、NVIDIA Container Toolkitをインストールします。
これはLinuxのDistributionごとにURLが変わるので、まずコンテナ内のLinuxのDistributionを見なければいけないです。
$ cat /etc/os-release
とすれば、OS情報が見れます。この中のIDとVERSION_IDをくっつけたものがDistribution名になります。
bashであれば、下記のコマンドで distributionという変数にDistribution名を格納できます。
$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
そしてこの distribution変数を使って、curlでapt用のパッケージリストをとってきます。
$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
$ sudo apt update && sudo apt install -y nvidia-container-toolkit
これで、dockerコンテナ起動時に、–-gpus all オプションをつければ、コンテナ内でGPUが利用できるようになっています。
$ docker run -it -d --gpus all --name [container_name] docker_image_name:tag
$ docker exec -it [container_name] sh
コンテナ内で nvidia-smiコマンドを実行して、GPU情報がでてくれば大丈夫です。
docker-composeでGPUコンテナを起動
docker-composeでコンテナを作成する場合は、–-gpusオプションと同等のオプションが無いため、もう少しやることがあります。
まず、nvidia-container-runtimeをインストールします。
$ sudo apt install nvidia-container-runtime
設定ファイルを /etc/docker/daemon.jsonに作成します。
{ "runtimes":
{ "nvidia":
{ "path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
これで、docker-composeの設定ファイルで runtime: nvidia ができるようになります。
docker-compose.ymlの例を記載します。
version: '2.3'
services:
[service_name]:
image: [image_name]:[tag_name]
container_name: [container_name]
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
tty: true
ports:
- 80:80
- 443:443
volumes:
- /var/host:/var/docker
このdocker-compose.ymlファイルがある場所で、docker-compose up -d でコンテナを立ち上げて、コンテナ内で nvidia-smiを実行し、GPU情報が見れればコンテナ内でもGPUが使えます。
おまけ(コンテナ内の環境設定)
作りたてのコンテナでは、GPU以外にもいろいろとインストール・設定することがあると思います。これもメモですが、だいたいこのあたりは使うだろうというものを書いておきます。
コンテナ内がubuntuの例で書きます。
$ apt-get update
これはすでに上記のGPU設定でやってますが、一応書きます。これでいろいろ必要なものをインストールできるようになります。
あと、gccとかmakeとかも入ってないのでこのあたりの開発コマンドを入れます。
$ apt update
$ apt install build-essential
pythonも使うなら、
$ apt-get install python3-distutils
$ apt-get install python3-dev
pipのインストールは
$ apt-get install wget
$ wget https://bootstrap.pypa.io/get-pip.py
$ python3 get-pip.py
ここまでやれば、AWSでubuntuのEC2インスタンスを立ち上げたぐらいの状態になってると思います。
ただひとつ困ったことがありました。dockerのシェル上で、Ctrl-pが使えないのです。(dockerのdetachのコマンドのため) Ctrl-pは、ひとつ前のコマンドを実行したいときに多用するので、これが使えないと困ります。一応2回押せばできるんですが、そんなのは無理です。 上矢印キーでもできるんですが、手をホームポジションから動かすのは嫌です。
ですので、Ctrl-pを使えるようにします。
~/.docker/config.json の設定ファイルの中に
"detachKeys": "ctrl-\\"
と書いて、detach key をCtrl-pとは違うキーに割り当てます。これで、Ctrl-pが使えるようになります。
これでubuntuで遊べるようになりました。せっかくなので、この状態をイメージに保存しておきたいと思います。イメージとして保存しておけば、この状態からコンテナを作成できるようになります。
$ docker commit [container_name] [image_name]:[tag_name]
これで、このコンテナが、[image_name]で保存されて、[tag_name]というタグが付いています。