(学習用環境構築メモ) DockerコンテナでJupyter Notebookを起動する。

# 概要
データ分析・機械学習を勉強するためにJupyter Notebookをインストールしたときのメモです。
勉強しようと思ったら講座でも書籍でも大体Jupyterの紹介がありますので、とにかく早く簡単にPythonの実行環境を整えたい方のために投稿します。Dockerなので環境の複製や共有も簡単にできます。

# 動作環境

```shell-session:環境情報
$ uname -a ; docker --version ; firefox --version
Linux hoge 4.17.2-1-ARCH ＃1 SMP PREEMPT Sat Jun 16 11:08:59 UTC 2018 x86_64 GNU/Linux
Docker version 18.05.0-ce, build f150324782
Mozilla Firefox 60.0.2
```

Dockerのインストールが完了していて、Activeになっている前提で記載しています。
入ってない場合は各環境に合わせて先にDockerのインストールをお願いします。
ホストOSがLinuxですが、Dockerが入っていればWindowsでもMacでも同じはずです。

# Jupyter Docker Stacks
[Docker Hub](https://hub.docker.com/u/jupyter/)(GitHubのDocker版)にJupyterコミュニティがDockerイメージを公開しているのでこれを利用します。
詳しくは以下のサイトを参考にしてください。

Jupyter Docker Stacks
http://jupyter-docker-stacks.readthedocs.io/en/latest/index.html

Dockerイメージは複数ありますので好きなものを選んでください。
大体入ってる[datascience-notebook]を選べば間違いありませんが、その分容量も大きいのでご注意ください。
最小限の[minimal-notebook](https://hub.docker.com/r/jupyter/minimal-notebook/)を選んで、必要なものはpipでインストールしていくやり方でもいいと思います。

取り敢えずnumpyやpandas、scikit-learnが入っていればいいので、ここでは[scipy-notebook]にします。

[datascience-notebook]:https://hub.docker.com/r/jupyter/datascience-notebook/
[scipy-notebook]:https://hub.docker.com/r/jupyter/scipy-notebook/

# 手順

### 環境構築
[scipy-notebook]をダウンロードします。

```shell-session:イメージ取得
$ docker pull jupyter/scipy-notebook

Using default tag: latest
latest: Pulling from jupyter/scipy-notebook
(省略)
Digest: sha256:8bd3258c2c49952c7237599151f61f664751867e453c3b582ffbd412d29d0cba
Status: Downloaded newer image for jupyter/scipy-notebook:latest
```

ダウンロードしたDockerイメージを確認します。

```shell-session:イメージ一覧
$ docker images
REPOSITORY                     TAG        IMAGE ID       CREATED         SIZE
jupyter/scipy-notebook         latest     5be90321fc2a   8 hours ago     4.56GB
```

イメージからコンテナを作成します。
--nameオプションを使用して任意の名前を付けておくと後で作業が楽です。

```shell-session:コンテナ作成&起動
$ docker run -p 10000:8888 --name jupyter jupyter/scipy-notebook
/usr/local/bin/start-notebook.sh: ignoring /usr/local/bin/start-notebook.d/*

Container must be run with group "root" to update passwd file
Executing the command: jupyter notebook
[I 09:14:47.697 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret
[W 09:14:48.062 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 09:14:48.123 NotebookApp] JupyterLab beta preview extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab
[I 09:14:48.123 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab
[I 09:14:48.141 NotebookApp] Serving notebooks from local directory: /home/jovyan
[I 09:14:48.141 NotebookApp] 0 active kernels
[I 09:14:48.141 NotebookApp] The Jupyter Notebook is running at:
[I 09:14:48.141 NotebookApp] http://7dae9a493ca7:8888/?token=8fbca5cf036bf78003c37b15e40906f266d36399864954cd
[I 09:14:48.141 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 09:14:48.142 NotebookApp] 
    
    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://7dae9a493ca7:8888/?token=8fbca5cf036bf78003c37b15e40906f266d36399864954cd&token=8fbca5cf036bf78003c37b15e40906f266d36399864954cd
```

これでイメージからコンテナが作成され、起動した状態になります。
出力結果にある通り、Jupyter Notebookにログインするためにはトークンを指定する必要があります。

任意のブラウザで`http://localhost:10000`に接続すると、パスワードまたはトークンを入力するログイン画面が表示されます。
出力結果からトークン("token="以降)をコピペしてログインしてください。トークンは環境によって異なります。自分の端末に表示されたトークンをコピペしてください。

もしくは、出力結果のURLのホストとポートを「localhost:10000」に変えて実行しても大丈夫です。
`http://localhost:10000/?token=8fbca5cf036bf78003c37b15e40906f266d36399864954cd&token=8fbca5cf036bf78003c37b15e40906f266d36399864954cd`
※パスワードを使うやり方もありますがここでは省略します。

これでJupyter Notebookを使えるようになりました。
右のNewボタンからPython3を選んでインタラクティブにPythonコードを記述できます。
[datascience-notebook]の場合はさらにJuliaとRも選べます。

![Jupyter Notebook](https://qiita-image-store.s3.amazonaws.com/0/265526/9d8613d3-49f4-3d7d-6bc6-1c6d419ec6cb.png)

コンテナを終了するには、ターミナルで`Ctrl + C`を入力します。

作成したコンテナを確認します。

```shell-session:コンテナ一覧
$ docker ps -a
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                     PORTS               NAMES
7dae9a493ca7        jupyter/scipy-notebook         "tini -g -- start-no…"   9 minutes ago       Exited (0) 3 seconds ago                       jupyter
```

IMAGE:jupyter/scipy-notebookから作成されたコンテナが名前:jupyterで状態は停止(STATUS:Exited)となっています。

### 起動
この記事ではデータ分析・機械学習の勉強用の環境としてDockerを利用しています。
ここまでが環境作り、これ以降は毎回環境を立ち上げる際の手順となります。

Dockerを起動します。
停止しているコンテナを起動します。

```shell-session:コンテナ起動&一覧
$ docker start jupyter # コンテナ起動
jupyter

$ docker ps # 状態を確認
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                     NAMES
7dae9a493ca7        jupyter/scipy-notebook   "tini -g -- start-no…"   17 minutes ago      Up 12 seconds       0.0.0.0:10000->8888/tcp   jupyter
```

STATUS:Upとなっているので起動したことが確認できます。

初回と同様、任意のブラウザで`localhost:10000`に接続します。
このとき、私の環境では初回ログイン時にブラウザでトークンが(パスワードとして)保存されていたためか、再度トークンを入力する必要がありませんでした。
トークン記録してない、覚えてないという場合は以下の方法でトークンを確認できます。

```shell-session:トークン確認方法
$ docker exec -it jupyter /bin/bash # コンテナに入る

jovyan@7dae9a493ca7:~$ jupyter notebook list # コンテナに入ってJupyter Notebookサーバーの確認
Currently running servers:
http://localhost:8888/?token=37e54ebd8f35171b14fcdafd11ea46b84dd3b7ea1fbe1d67 :: /home/jovyan
```

トークンはコンテナを立ち上げるたびに新しくなるようですが、コンテナ作成時のトークンでもログインできるようでした。ここではセキュリティについて拘らないこととします。

- `docker exec`コマンドは、対象のコンテナ(jupyter)で任意のコマンドを実行します。この場合は`/bin/bash`ですが、これは環境によって変えてください。`docker attach`でも実現できますが、`exit`や`Ctrl+D`を誤って入力したときにコンテナが停止してしまうのでexecを使うことをお薦めします。

今回のコンテナ作成方法だと、前回停止したときに作成したファイルなどは削除されずに残っているので、続きから学習をすすめることができます。

# まとめ

```shell-session:環境構築
$ docker pull jupyter/scipy-notebook
$ docker run -p 10000:8888 --name jupyter jupyter/scipy-notebook
```

```shell-session:毎回起動
$ docker start jupyter
```

# Tips

### ●Pythonライブラリのインストール・アップデート

Pythonライブラリの管理は、`docker exec`でコンテナに入ってpipコマンドで行います。

```shell-session:pip使用例
jovyan@7dae9a493ca7:~$ pip install pyperclip # pyperclipをインストール

jovyan@7dae9a493ca7:~$ pip install --U numpy # numpyをアップデート
```

LinuxまたはMac OSを使用している場合は、ターミナルからコンテナに入らずとも、起動しているJupyter Notebookで`!`を付けるとコマンドを実行できます。

![Jupyter Notebook](https://qiita-image-store.s3.amazonaws.com/0/265526/9e2deb4f-4dba-479a-8038-a7e3b4356ebf.png)


### ●パッケージの管理
もし必要な場合は、ベースイメージにUbuntuを使用しているのでapt-getコマンドでパッケージの管理ができます。使用例として、gitをインストールしてコンテナ内でcloneすると楽です。書籍によってはコードサンプルをGitHubに公開しているものも多いので。
ただ、デフォルトのユーザーだと「Permission denied」となるので、execコマンド実行時にユーザ:rootを指定します。


```shell-session:コンテナにgitをインストール
$ docker exec -it --user root jupyter /bin/bash # rootユーザでコンテナに入る

root@7dae9a493ca7:~# apt-get install git # gitをインストール
```