書籍「Pythonで学ぶ強化学習」のサンプルコードを実行可能な環境をdockerで構築 (GUI出力対応)

# 概要
強化学習の勉強を[「Pythonで学ぶ強化学習」](https://www.amazon.co.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Python%E3%81%A7%E5%AD%A6%E3%81%B6%E5%BC%B7%E5%8C%96%E5%AD%A6%E7%BF%92-%E5%85%A5%E9%96%80%E3%81%8B%E3%82%89%E5%AE%9F%E8%B7%B5%E3%81%BE%E3%81%A7-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E4%B9%85%E4%BF%9D/dp/4065142989/ref=sr_1_1?adgrpid=53784669096&hvadid=338568511613&hvdev=c&hvlocphy=1009196&hvnetw=g&hvpos=1t1&hvqmt=e&hvrand=3316749406769594287&hvtargid=kwd-599476674395&jp-ad-ap=0&keywords=python%E3%81%A7%E5%AD%A6%E3%81%B6%E5%BC%B7%E5%8C%96%E5%AD%A6%E7%BF%92&qid=1554466974&s=gateway&sr=8-1)でしており、サンプルコードを実行可能なdockerを構築してみたので紹介します。 
こちらの書籍はサンプルコードが充実していることに加えて、比較的新しい手法が説明されており、強化学習の現状把握のスタートにはとてもおすすめです。

[書籍サンプルコードリポジトリ](https://github.com/icoxfog417/baby-steps-of-rl-ja)

# 環境
macOS Mojave(10.14.4)
※Ubuntu 18.04版も紹介

# 目指す環境
- python==3.5
- tensorflow==1.12.0
- docker内でグラフプロット等の**GUI**使用可能

# 下準備
<a name="1"></a>
### 1. dockerのインストール
自分の環境にdockerをインストールします。
Mac向け参考記事：[DockerをMacにインストールする (更新：2018/5/14)](https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81)
※私の環境ではXquartzの設定後に上手くいかず、PC再起動で上手くいきました。
Ubuntu向け参考記事：[Ubuntuにdockerをインストールする](https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d)

### 2. ホスト側のGUI表示用設定
共通参考記事：[Dockerコンテナの中でGUIアプリケーションを起動させる](https://unskilled.site/docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%B8%AD%E3%81%A7gui%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B/)

#### Mac
- socatの導入・起動
- Xquartzの導入・起動  
XQuartzが起動したらセキュリティ設定（環境設定>セキュリティ）を変更しておきます。
 1. 「接続の認証」をOFF
 2. 「ネットワーク・クライアントからの接続」をON

Mac向け参考記事：[DockerをMacにインストールする (更新：2018/5/14)](https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81)
&emsp; &emsp; &emsp; &emsp; &emsp; &emsp; &emsp; [Docker上のGUI出力をMacで表示](https://qiita.com/uedashuhei/items/3f6f8612b5c4a2b00b1a)

#### Ubuntu

以下コマンドを実行します

```bash
xhost local:
```

### 3. NVIDIAドライバーとnvidia-docker2のインストール(GPU使用の場合)
Ubuntu向け参考記事：[nvidia-docker 2 を Docker CE (安定版) と共に Ubuntu 18.04 へインストールする](https://qiita.com/dyoshiha/items/e58be9ee5c19bee1a0cd)

# dockerの設定
### 3. Dockerfile
ベースイメージはtensorflow:1.12.0-py3を使用してそれに必要なpythonモジュールをインストールしています。
必要はパッケージは書籍のサンプルコードのGitリポジトリ内にrequirements.txtで入っているので、それをコンテナ内にコピーしてpipでインストールするだけになります。
ホスト側のXサーバーへの接続がセキュリティー的にrootユーザーからはできないらしく、③で別ユーザーを作成してユーザー切り替えを行っています。

```docker:Dockerfile
# GPUの場合
#FROM tensorflow/tensorflow:1.12.0-gpu-py3
# ①CPUの場合 
FROM tensorflow/tensorflow:1.12.0-py3
COPY into_container/requirements.txt /root/

# ②パッケージインストール
RUN add-apt-repository -y ppa:jonathonf/vim \
 && apt-get update \
 && apt-get install -y git vim xterm sudo python3-tk \
 && pip3 install --upgrade pip \
 && pip3 install -r /root/requirements.txt

# ③ユーザーの切り替え
RUN groupadd -g 1000 developer && \
    useradd  -u 1000 -g 1000 --groups sudo --create-home --shell /bin/bash developer && \
    echo 'developer:P@ssw0rd' | chpasswd
USER developer
WORKDIR /home/developer
```

### 4. ビルド
普通にビルドすればOKです。

```build.sh
docker build -t baby-steps-env .
```

### 5. コンテナ起動

runする際に以下の設定を行っています。

- コンテナ内の環境変数DISPLAYにホスト側のディスプレイを設定
- 書籍のサンプルコードのディレクトリをコンテナ内にマウント
- ホストのXサーバーのソケットファイルをコンテナ内にマウント

使用する際は引数-vで指定している'localdir'を消して、ホスト側の書籍のサンプルコードディレクトリを絶対パスにしてください。
 

```run.sh
# GPUの場合
#nvidia-docker run --rm --name baby-steps-container -it \
#									-e DISPLAY=host.docker.internal:0.0 \
#									-v 'localdir':/home/developer/baby-steps-of-rl-ja \
#									-v /tmp/.X11-unix/:/tmp/.X11-unix \
#									baby-steps-env bash

# CPUの場合
docker run --rm --name baby-steps-container -it \
									-e DISPLAY=host.docker.internal:0.0 \
									-v 'localdir':/home/developer/baby-steps-of-rl-ja \
									-v /tmp/.X11-unix/:/tmp/.X11-unix \
									baby-steps-env bashdocker build -t baby-steps-env .
```

### 6. 実行
Dockerfile, build.sh, run.shのある階層で以下を実行します。

```bash
$ sh build.sh
$ sh run.sh
```

### 7. 動作確認

コンテナ内のbashコンソールで

```bash
$ xterm
```

と入力してEnter。
これでウィンドウが立ち上がれば成功です。

### 8. Gitリポジトリ
Gitに今回紹介したソースをあげていますのでよければご利用ください。
Mac用 : [kinziro/baby-steps-mac-env_on_docker](https://github.com/kinziro/baby-steps-mac-env_on_docker)
Ubuntu用 : [kinziro/baby-steps-ubuntu-env_on_docker](https://github.com/kinziro/baby-steps-ubuntu-env_on_docker)

# 参考にさせて頂いたサイト
[DockerをMacにインストールする (更新：2018/5/14)](https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81)
[Docker上のGUI出力をMacで表示](https://qiita.com/uedashuhei/items/3f6f8612b5c4a2b00b1a)
[Ubuntuにdockerをインストールする](https://qiita.com/tkyonezu/items/0f6da57eb2d823d2611d)
[Dockerコンテナの中でGUIアプリケーションを起動させる](https://unskilled.site/docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%81%AE%E4%B8%AD%E3%81%A7gui%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%82%8B/)
[nvidia-docker 2 を Docker CE (安定版) と共に Ubuntu 18.04 へインストールする](https://qiita.com/dyoshiha/items/e58be9ee5c19bee1a0cd)