Dockerで最強のKaggle・機械学習・ディープラーニング環境を作成

DockerでTensorflowやGPU含めた全部入りの機械学習環境を作る。
面倒な環境構築を簡略化して、どこでも同じ環境が再現できる。

JupyterによるWebアクセスに加え、sshdにより、VScode(python)、pro仕様のPycharm(python)
やIntelliJ(Scala, Java, Kotlin)が使える。 

####※windowsの仕様により現在はUbuntuなどLinux系のみGPU対応。

###1. 対応
#####1.1 言語
Python, Kotlin, Scala, Java
#####1.2 ライブラリ
- 一般的な機械学習ライブラリ: sklearn, numpy, scipy等(Anacondaデフォルト)
- ディープラーニング: TensorFlow2.0 (Keras内包)
- ケモインフォマティクス: Rdkit
- 分散分析: Spark
- 機械学習ライブラリ: Xgboost, lightgbm, Factorization Machines, Regularized greedy forest
- ハイパーパラメータの調整: Bayesian Optimizer
- 機械学習拡張ツール (Stacking): mlxtend 
- 強化学習: OpenAI Gym

###2.前提
- Docker、Docker‐composeがインストール済みであること。
- GPUを使用する場合はCUDAがインストール済みであること。

###3.手順
#####3.1 GPU対応(Ubuntu等のLinucのみ）
Dockerを動かすOSにて下記を実行。

```
sudo apt-get install nvidia-docker2
sudo pkill -SIGHUP dockerd
```

以後、docker run は--runtime=nvidia オプション、docker-composeはruntime: nvidiaの項目を追加することでGPU対応となる。

#####3.2 Dockerfileの作成
KaggleコンテナはGPU非対応のためcontinuumio/Anaconda3コンテナを使用する。

Sparkは最新版をインストールし、Java、Kotlin、gradleはSDKMANを使用してインストール。

#####Dockerfile

```Dockerfile
FROM continuumio/anaconda3

## add user & SSH
RUN apt update && apt install -y openssh-server curl zip unzip vim
RUN mkdir /var/run/sshd
ENV USER UserName
ENV SHELL /bin/bash
RUN apt install -y sudo
RUN useradd -m ${USER}
RUN gpasswd -a ${USER} sudo
RUN echo "${USER}:myPasswd" | chpasswd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

## spark
RUN curl -O http://ftp.tsukuba.wide.ad.jp/software/apache/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz &&\
tar -zxvf spark-2.4.3-bin-hadoop2.7.tgz &&\
mv spark-2.4.3-bin-hadoop2.7 /usr/local &&\
ln -s /usr/local/spark-2.4.3-bin-hadoop2.7 /usr/local/spark 
RUN echo "export SPARK_HOME=/usr/local/spark"  >> /etc/environment
RUN rm spark-2.4.3-bin-hadoop2.7.tgz

## java,kotlin,gradle
ENV SDKMAN_DIR "/usr/local/sdkman" 
SHELL ["/bin/bash", "-c"]
RUN curl -s "https://get.sdkman.io" | bash &&\
source "/usr/local/sdkman/bin/sdkman-init.sh" \
;sdk install java;sdk install kotlin;sdk install gradle;sdk install scala;sdk flush temp;
#sdk install sbt;sdk install spark;

## android
# RUN wget https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
# RUN mkdir -p /Android/sdk
# RUN unzip sdk-tools-linux-4333796.zip -d /Android/sdk
ENV ANDROID_HOME /Android/sdk

## path and env for the user
RUN echo "/bin/bash" >> /etc/profile.d/default.sh
RUN echo "alias python="/opt/conda/bin/python"" >> /home/${USER}/.bashrc
RUN echo "export SDKMAN_DIR="/usr/local/sdkman""  >> /etc/environment
RUN chmod 755 /usr/local/sdkman/bin/sdkman-init.sh
RUN source /usr/local/sdkman/bin/sdkman-init.sh;echo "PATH=${PATH}:/usr/local/spark/bin:$ANDROID_HOME/bin" >> /home/${USER}/.bashrc
RUN echo "bash -c "/usr/local/sdkman/bin/sdkman-init.sh"" >> /etc/profile.d/default.sh
RUN echo "if [ -f ~/.bashrc ]; then  . ~/.bashrc;  fi" >>/home/${USER}/.bash_profile
RUN chmod 755 /etc/profile.d/default.sh

## for root login
# RUN sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config &&\
# echo "root:myRootPasswd" | chpasswd
# ENV NOTVISIBLE "in users profile"
# RUN source /usr/local/sdkman/bin/sdkman-init.sh;echo "PATH=/usr/local/spark/bin:${PATH}" >> ~/.bashrc &&\
# echo "if [ -f ~/.bashrc ]; then  . ~/.bashrc;  fi" >>~/.bash_profile

## RDkit
RUN conda install -c rdkit rdkit

## Deep Neural net
RUN pip install -U pip && \
pip install tensorflow-gpu==2.0.0-alpha0 && \
pip install python-louvain && \
conda install -y cudnn cudatoolkit numba
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES utility,compute

## Others
RUN pip install cairosvg && \
pip install fastprogress japanize-matplotlib && \
pip install xgboost &&\
pip install lightgbm &&\
pip install rgf-python &&\
pip install mlxtend &&\
pip install bayesian-optimization

## Factorization Machines
# apt install -y --reinstall build-essential && \
# apt-get install -y python-dev libopenblas-dev && \
# git clone --recursive https://github.com/ibayer/fastFM.git && \
# cd fastFM && \
# pip install -r ./requirements.txt && \
# PYTHON=python3 make TARGET=core2 && \  
# pip install . && \

## Reinforcement learning
RUN apt -y install git gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev  python3-tk tk-dev python-tk libfreetype6-dev python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig
RUN pip install gym && \
pip install gym[classic_control] &&\
pip install gym[box2d] && \
git clone https://github.com/openai/baselines.git &&\
cd baselines &&\
pip install -e . &&\
pip install pytest &&\
pip install gym-retro

## clean files
RUN apt clean
```
- UserName, myPasswdは自分のログイン情報で設定する。
- Factorization Machinesのコンパイルは環境依存性があり、一部のCPUだと通らない。
（Xeon系は問題ないが、Core i7だと厳しめ）

Androidは趣味……。

#####4. docker-composeの作成と実行
Jupyterはポート8888、sshはポート22を使用。


docker‐compose.yaml

```yaml
version: "3"
services:
  jupyter:
    #docker-composeの実行場所
    build: .
    volumes:
      #コンテナとの共有フォルダ
      - ~/tmp:/tmp/working
    working_dir: /tmp/working
    ports:
      - '8888:8888'
      - '22:22'
    ##GPUを使用
    #runtime: nvidia
    ##jupyter
    #command: jupyter notebook --ip=0.0.0.0 --allow-root --no-browser --NotebookApp.token='' 
    ##ssh
    command: /usr/sbin/sshd -D
```
GPUを使用する際はruntime: nvidia

あとはDockerfile, docker-compseを置いたフォルダで下記コマンドでビルド、起動する。

```
docker-compose up --build
```
再起動後などコンテナ終了後はDockerfile, docker-compseを置いたフォルダにて
下記コマンドでコンテナを起動させる。

```
docker-compose up
```

jupyterが/bin/bashで起動しないためsshと同時起動できない。両立させるためにはsshをデーモンに登録するか、sshからjupyterを起動させる必要がある。


適宜追記予定。