jupyter公式/datascience-notebook でGPU使えるようにしたのでdockerfile晒してメモ

dockerでデータ分析環境を作るの、本当にラクですね。
ウチでは元々RStudio(rocker/tidyverse)をメインで使っているのですが、
タスクによってはやはりpython/tf環境が欲しいです。
最短で使い始められるtensorflow-gpu環境を作ってみたので記事に晒します。

# どのイメージ使おう
「車輪の再発明を避けたい」ので、
「なるべく利用者の多いベースイメージを使う」ようにしています。
この理屈だと<b>「jupyter公式」と「nvidia cuda 公式」を組み合わせて使う</b>のが最適そうです。

幸い、どちらもubuntu18(2020/7時点)をベースにしていますので、
単純にdockerfileをガッチャンコするだけで動くはずです。

##プロジェクトjupyter公式イメージ
https://jupyter.org/
https://hub.docker.com/r/jupyter/datascience-notebook/

###選んだのは datascience-notebook
https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html#jupyter-datascience-notebook
最小要素の「jupyter/base-notebook」からはじまり、
全部乗せの「jupyter/all-spark-notebook」まであるのですが、
[ R, Python, Julia ]とデータサイエンス3大言語環境が整った
「jupyter/datascience-notebook」をベースに選びました。


# nvidia cuda 公式
https://hub.docker.com/r/nvidia/cuda

ソースはgitlabに公開されています
https://gitlab.com/nvidia/container-images/cuda/-/blob/master/dist/10.2/ubuntu18.04-x86_64/base/Dockerfile
こちらは BSD3 ライセンスですね。


# dockerfile をガッチャンコしよう
dockerfileの頭に ```FROM jupyter/datascience-notebook ``` を書いたら、
後は上記のソースファイルからcuda設定関連の行をそのままコピペします。


```dockerfile
FROM jupyter/datascience-notebook

USER root


# この部分 Copyright (c) 2019,2020 NVIDIA CORPORATION. All rights reserved.
### install cuda - copied from nvidia cuda dockerfiles cuda 10.2
# https://gitlab.com/nvidia/container-images/cuda/-/blob/master/dist/10.2/ubuntu18.04-x86_64/base/Dockerfile

RUN apt-get update && apt-get install -y --no-install-recommends \
    gnupg2 curl ca-certificates && \
    curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub | apt-key add - && \
    echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/cuda.list && \
    echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list && \
    apt-get purge --autoremove -y curl && \
    rm -rf /var/lib/apt/lists/*

ENV CUDA_VERSION 10.2.89
ENV CUDA_PKG_VERSION 10-2=$CUDA_VERSION-1
# For libraries in the cuda-compat-* package: https://docs.nvidia.com/cuda/eula/index.html#attachment-a
RUN apt-get update && apt-get install -y --no-install-recommends \
    cuda-cudart-$CUDA_PKG_VERSION \
    cuda-compat-10-2 \
    && ln -s cuda-10.2 /usr/local/cuda && \
    rm -rf /var/lib/apt/lists/*

# Required for nvidia-docker v1
RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \
    echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf

ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64

# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_REQUIRE_CUDA "cuda>=10.2 brand=tesla,driver>=396,driver<397 brand=tesla,driver>=410,driver<411 brand=tesla,driver>=418,driver<419 brand=tesla,driver>=440,driver<441"

##### ユーザを戻しておく
USER jovyan

##### nv-cuda インストール完了

# この下に、個人用の設定を追加...

```
と、こんな感じです。

あとはtensorflow-gpuに、よく使うパッケージ等もdockerfile内でインストールしておくと後で時間の節約になります。
僕のを参考として晒します：

```dockerfile
# ... dockerfile 続き
# ターミナルでzsh使いたい
RUN apt-get install -y zsh

# conda/pythonの部
# コレ書かないと失敗することがある
RUN conda config --set channel_priority false
RUN conda update --all
# パッケージ入れる
RUN conda install -c anaconda tensorflow-gpu
RUN conda install -c anaconda tensorflow-hub
RUN conda install -c anaconda tensorflow-datasets
RUN conda install -y pydot graphviz

# カメラ関連 activate webcam usage for jovyan
# great write-up:  https://medium.com/@zwinny/docker-using-webcam-9fafb26cf1e6
# docker run する時に --device=/dev/video0:/dev/video0 を付けます
USER root
RUN apt-get install -y ffmpeg v4l-utils
RUN usermod -a -G video jovyan

# Rの部
RUN conda install -c r r-tidyverse r-pacman
COPY preload_packages.R /home/jovyan/
RUN Rscript /home/jovyan/preload_packages.R

# preload_packages.R の中身はこんな感じに列記してます
# pacman::p_load(selectr, xml2, rvest, RSelenium, XML, scales, ggrepel, stringi, 
# htmlwidgets, plotly, showtext, ggpubr, foreach, doParallel, tictoc, stringr, tidylog,
# datapasta, googledrive, aws.s3, rdrop2, magrittr, jsonlite, lubridate, readr, glue,
# googlesheets4, gt, lgr)

```



# docker run しよう - スクリプトにしとくと便利
ベストなやり方は docker-compose とか jupyter hubを使って多人数環境をちゃんとつくる事だと思うのですが、
ウチは割と適当にあちこちでマシン構成弄ったりするゆるめな環境なので、
単純に「1ユーザ1インスタンスで docker run する」事を前提に、
起動用scriptだけ、gitで共有しています。

参考までに docker run の部分だけ晒します。(各$変数の意味は変数名で察して下さい...)

```run_jlab.sh
# --restart を付けたので実行済みの事がある。実行済みであれば stop & rm
docker ps -aq --filter "name=$containername" | grep -q . && docker stop "$containername" && docker rm -fv "$containername"

docker run -d --restart always \
    -v /dev/shm:/dev/shm \
    --gpus $gpu_device \
　　 --device=/dev/video0:/dev/video0 \
    -e TZ=Asia/Tokyo \
    -e GRANT_SUDO=yes \
    --user root \
    -p $dport:8888 \
    -p $tfboard:6006 \
    --name $containername \
    -v "$_mailabmulti_root":"/home/jovyan/`hostname`_$(basename $_mailabmulti_root)_p$dport" \
    -v "/home/taiyo/py_jlab_common":"/home/jovyan/`hostname`_common" \
    mailab/py_jl \
    start.sh jupyter lab --NotebookApp.password="sha1:##########loginpasswordのハッシュ値#########"

```

# 無事起動できました！
<img width="456" alt="Screenshot 2020-07-16 at 11.35.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255842/c803b4a7-0d24-1018-6a8b-798468885bad.png">

![Screenshot 2020-07-16 at 11.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255842/36cc4e8a-f88c-8d7c-ca0b-16971c7c13b6.png)

これでゴリゴリtfが叩けます〜

稚拙なやり方ですが、「とりあえずさっさとTF叩かせろグルぁ」的なニーズには答えられると思います。


# で、 docker pull tensorflow/tensorflow:latest-gpu-jupyter じゃアカンの？

全然良いですね。
TFしか触らないならそちらの公式が良いと思います！！！

jupyter公式レポは、R/Julia/Spark他、データサイエンス系のツールが一通り揃っているのがステキなのです。

ってJulia触れる予定はしばらく無いけどな！！

でもRはtidyverseを知るとuntidyデータの整理や珍しいアルゴリズム試すのがめちゃラクになりますのでウチでは必須...