データサイエンティストなら誰もが通る、リモートサーバのJupyter Notebook (Lab)へのアクセス方法まとめ

# Jupyter Notebookって？

Jupyter Notebook(Lab) とは、Webブラウザ上で動くIDEのことです。
画像処理結果やデータグラフなどが綺麗に表示される為、データサイエンスにはよく用いられます。

それ以上に、利用価値があるってよく使われる例が、**GPUやメモリを大量に積んだサーバ上でプログラムを動かしたい**という場合です。
画像処理では主に計算スピード面で、自然言語処理ではメモリ面で、それぞれMacだけでは対応できない場合が多いです。そこで、UIはMacBook上で利用し、計算処理だけは強いサーバだけに任せてしまうことが多いです。

こんなイメージのことをしたいという時、Jupyter Notebook(Lab)を利用します
<img width="972" alt="スクリーンショット 2018-08-10 19.57.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/182970/07638e10-7b10-94b8-77c7-3af916eb2ae2.png">

この時に少し問題になるのが、どのようにサーバを建てるか、どのようにアクセスするか、それぞれについて実はネットワーク環境によって**様々に変わってきます**。

今回は状況によって変わるJupyter Notebookアクセス界隈について知識をサーベイしたので、まとめたいと思います。

#Jupyter Notebook基本知識

Jupyter Notebook(Lab)の基本的な説明

## Jupyter Notebook導入方法

基本的にはオールインパッケージであるAnacondaを利用すれば一緒についてきます。

入っていない場合、シェルにpipコマンドを利用し

```
$ pip install jupyter
```

とすると、Notebook・Lab同時に二つインストールされます。
pipコマンドはpythonインストールすれば入っているらしいので、無い場合はPythonが無いか確認してみてください。

## Jupyter Notebook利用方法

インストールが終われば

```
$ jupyter notebook
```
とすればnotebook用のWebサーバが起動します。

```
$ jupyter lab
```
とすれば、lab用のWebサーバが起動します。（NotebookとはUIが違います）

文字通りWebサーバが起動するので、特にnginxなどで個別に設定してあげる必要はありません。

## Jupyter Notebook便利機能

> https://qiita.com/simonritchie/items/d7dccb798f0b9c8b1ec5
> Jupyter 知っておくと少し便利なTIPS集

こちら拡張機能についてまとめてあるので、一応こちらも紹介させてください。


#Case別アクセス方法まとめ

さて、ここから本題になります。
基本的に接続方法は直アクセスか、ポートフォワードの2種類があります。
基本的にポートフォワードはどんな場合も繋がり、制約も少ないです。おすすめしておきます。

# Case1:MacからLAN内のサーバにアクセスする方法

<img width="787" alt="スクリーンショット 2018-08-10 20.43.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/182970/8fca9d8e-f5ac-f2cb-19ff-7c6e115c0efd.png">

この場合、直アクセスという方法を取ることができます。もちろん後述のポートフォワーディングを使用しても問題ありません。今回は直アクセスの方法を紹介します。

## 直アクセス手法
まずは、サーバ側で設定ファイルを作成しましょう。
```
[server@192.168.1.2] ~$ jupyter notebook --generate-config
```
そうすると、サーバ側に~/.jupyter/jupyter_notebook_config.pyが作成されるので、こちらに設定を書き込みます。

そして、サーバ側の~/.jupyter/jupyter_notebook_config.py内にある以下の項目について、それぞれ設定します。

```
c.NotebookApp.ip = '192.168.1.2'(サーバip)
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888(好きなポートを選んでよし)
```

これで、基本的な設定は終わりで、

```
[server@192.168.1.2] ~$ jupyter notebook
```

とすると、

```
    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://192.168.1.2:8888/?token=19dd038470d91d8eea381907e99c77f82b95348220f1a834

```
といったログが出てきますので、これをそのままローカルであるMacのブラウザ上にコピペすればアクセスでき、そのままサーバ環境のJupyter Notebookが利用できます。Jupyter Notebook上の演算は全てサーバ側で行われます。やったね！


# Case2:Macから外の箱入り娘サーバへアクセスしたい！

<img width="1036" alt="スクリーンショット 2018-08-10 21.34.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/182970/32a38ab7-769f-534c-fe40-d3f1b214b345.png">

このケースが一番多いかと思われます。AWSなどのクラウドにアクセスする場合もこっちの方がセキュアでいいです。それと、ファイアウォールで囲われたネットワーク内でどうしても作業しなきゃいけない場合があります。　まぁ、VPNで囲ってもらって、そこから直アクセスという手もありますが、今回はポートフォワーディング手法を紹介します。（こっちの方が直アクセスよりセキュアです）

## ポートフォワーディング手法

ポートフォワーディングについての解説はこちら。
>https://qiita.com/Ayaka14/items/449e2236af4b8c2beb81
>SSHポートフォワーディングを知った話

ポートフォワーディングは、あるリモートサーバを踏み台に別のリモートサーバにアクセスするやり方のことですが、１つのリモートサーバ内で、**ssh用の穴：port22でしか許可されていないけど同じ穴を通して別のportも使いたい**という時に使えます。

まずローカルMacのSSH設定についていじる必要があります。

```
[Macbook@192.168.1.2] ~$ vim ~/.ssh/config
```

ここで、サーバにSSHでアクセスする設定を書いているかと思います。
えっ、なにそれ？という方はこちらの記事をどうぞ。詳しく書かれています。

>https://qiita.com/passol78/items/2ad123e39efeb1a5286b
> ~/.ssh/configについて

ここで、

```
Host (SSH接続先)
    Hostname (略称)
    User (UserName)
    Port (使用ポート)
    IdentityFile (鍵のファイル場所)
```
と設定されているかと思いますが、ここにJupyter設定ポートが8888であれば、


```
Host (SSH接続先)
    Hostname (略称)
    User (UserName)
    Port 22(使用ポート)
    IdentityFile (鍵のファイル場所)
    LocalForward 8888 localhost:8888
```

と最後の１行を足します。この部分は、LocalForward [Mac側で設定したいport] [実際にアクセスするアドレス:port]といった形です。
この状態でSSHを行うと、**Mac側のローカルport8888にアクセスすれば、port22を通してサーバのport8888にアクセスしてくれる状態になります。**

あとは、サーバ側をそれ用に設定を行うだけで接続できるようになります。

まずは設定ファイルを生成（1回で大丈夫です）

```
[server@???.???.???.2] ~$ jupyter notebook --generate-config
```

次に、以下のようにサーバの~/.jupyter/jupyter_notebook_config.pyの内容をいじります。

```
c.NotebookApp.ip = 'localhost'(ここは必ずこう）
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888(先ほど~/.ssh/configで設定したポート)
```

そして、Jupyter Notebookを起動

```
[server@???.???.???.2] ~$ jupyter notebook
```

こうすると、以下のログが出力されるので、

```
    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=19dd038470d91d8eea381907e99c77f82b95348220f1a834

```

となりますので、そのままブラウザにコピぺでJupyter Notebookに接続ができます。もちろんこのJupyter Notebookはサーバ側で立ち上がっていますので、このNotebookで処理を投げるとサーバ側で処理を行ってくれます。やったぜ。

# Case3:WindowsでCase1の場合は？

これに関しては、基本的に同じことをRloginなどのターミナルソフトで作業が完結できるので簡単にできます。この辺は同じことをなぞれば大丈夫なはずです。（わからなきゃコメください）

# Case4:WindowsでCase2の場合は？

まず、Windows Subsystem for Linuxっていうのがあって、これを利用してMacのように~/.ssh/configで接続するのが一つの手です。
これをしたく無い場合、teratermなどのターミナルソフトじゃないと嫌！という場合は、
ターミナルソフトでポートフォワーディングの設定を行ってください。

>http://www.j-oosk.com/teraterm/port-forward/787/
>TeraTerm SSH転送（ポートフォワード）機能を利用した多段接続

こちらを参考にポートフォワーディングをやってみてください！（未確認で申し訳ない・・・）


# まとめ

以上が知識をまとめた結果になります。
こんな場合接続できんかったという場合があれば、コメをいただければ必ず返答しますので、コメください。よろしくお願いします。🙇‍♂️

よきデータサイエンスライフを！