EC2上にどこからでも簡単にアクセスできるjupyter lab環境を構築する

# 3行で
* EC2のdeep learning用AMIを使えばよく使うライブラリだのCUDAだのは導入済み
* インスタンス起動時にjupyter lab自動起動して、かつ外部からブラウザを通じてアクセスできるようにできる
* EIPを使うか、動的DNSを使ってアクセス先のアドレスを固定すればブラウザのブクマだけでアクセスできる。動的DNSは無料でも使える


# モチベーション
* いつでもどこでも同じ環境を使って開発したい
* 案件ごとに環境を分離したいし、そのための設定に手間をかけたくない
* EC2のdeep learning用AMIを使ってjupyter labを外部からアクセスできるようにした。ついでに動的DNSでアドレスを固定した。

# 注意
他の人のQiitaからの寄せ集めなので、あまり新規性はないです。

# 必要な作業
全体像は以下
* EC2インスタンスの作成
* EC2インスタンスへのSSH接続
* EC2インスタンスへのHTTPアクセス許可
* jupyter lab自動起動設定
* (オプション)EIPの設定
* (オプション)動的DNSの設定


# EC2インスタンスの作成
まずキーペアを作りましょう。
EC2インスタンスは当然AWS上にできるので、何らかの方法で遠隔操作する必要があります。
まず、一番基本的なSSHで接続したいわけですが、そのためにはキーペアが必要です。

Amazon EC2 のキーペア
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html
ページ最下部にやり方が書いてあります。windowsを使う場合、PuTTYを使うと思うので、ppkで保存しておいてください。
（注：「ナビゲーションペイン」ってのはEC2コンソールの左側のバーのことです。わからなかった・・・。）

キーペアができたらここを押してあとは指示に従うだけ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/9ce0d1ae-9f8b-156f-dcc8-ceecd46a6fa9.png)


Amazon マシンイメージはDeep Learning AMIのうちのどれかを選びましょう。
私はDeep Learning AMI (Ubuntu 18.04) Version 27.0を選びました。
無料利用枠じゃないですが、小さいインスタンスタイプを選んでおけば大した額にはなりません。

参考
https://aws.amazon.com/jp/ec2/instance-types/t2/
デバッグ用にはt2.mediumで十分かなと。0.0464 USD/hourです。

# EC2インスタンスへのSSH接続
接続の方法はいくつかありますが、スタンドアロンSSHクライアントを使ったSSH接続が一番シンプルだと思います。
(windowsの場合)下記参照のこと。

PuTTY を使用した Windows から Linux インスタンスへの接続
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/putty.html

パブリックDNSはこの、右側に表示されている値です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/e5cf3893-dab0-ec04-cdd6-c3bb7823cd74.png)

ただしこのパブリックDNS、インスタンスを停止して再起動すると値が毎回変わります。
そのたびにSSHクライアント側も設定をいじらなくてはいけません。
これを回避する方法は「(オプション)動的DNSの設定」で述べます。

ともあれこれで、EC2に外部からアクセスしてなんやかんや中身をいじれるようになりました。

# EC2インスタンスへのHTTPアクセス許可
最終的にはEC2上のjupyter labに外部からブラウザを通じてアクセスしたいので
HTTPでのアクセスを許可しておきます。
これはEC2コンソール側で行う操作です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/674b5f5e-b430-b678-7dd2-c0b7bb733b78.png)
このlaunch-wizard-*(なにかの番号)をクリックするとセキュリティグループの操作画面にいけます。

Inbound rulesのタブを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/bcf4316f-9a2f-23c2-c462-88d7b1fa81c7.png)
デフォルトだとSSHしかないと思いますが、ここにCustom TCPを追加します。

edit inbound rulesを押すと次のような画面になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/d70dfbd2-cac5-8e75-aa4b-545658a07227.png)
Add rulesを押すと行が増えるので、Custom TCP、port 8888、Sourceに0.0.0.0を登録します。
これで任意のソースからポート8888へのTCPでのアクセスが許可されました。
（注：HTTPも選択肢にありますが、ポートが80固定なので、8888を開けるにはCustom TCPで行います）

# jupyter lab自動起動設定
Deep Learning AMIにはjupyter labがデフォルトでインストール済みです。
ただし、少し設定を変更します。
下記参考のこと。

Jupyter事始め
https://qiita.com/taka4sato/items/2c3397ff34c440044978

/etc/rc.localにjupyter lab起動用のシェルスクリプトを叩くよう記述しておけばOKです。

ここまでうまく行っていれば、ブラウザのURL欄に
\<パブリックDNS>:8888　と入力すればjupyter labにアクセスできます。
（例：パブリックDNSがec2-3-88-70-204.compute-1.amazonaws.comならURLに入力する値はec2-3-88-70-204.compute-1.amazonaws.com:8888）

# (オプション)EIPの設定
このままだと、インスタンスを再起動するたびにパブリックDNSが変わってしまって、毎回それに合わせてアクセス先が変わって不便です。
対策として、インスタンスに固定のIPを振ることができます(有料)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/e9804251-22aa-1a05-316a-8608350688b6.png)
ここで、Elastic IPの割り当てから、インスタンスにIPを割り当てられます。
EIPは便利ですが、インスタンス停止中にわずかながら料金が発生します。(0.01 USD/hourぐらい)
（無料、になるのはインスタンス起動中です。この場合EIPは無料ですがインスタンスの料金がかかりますし、なんかしらの料金は発生するわけです）

# (オプション)動的DNSの設定
やりたいことは、「いつでも同じ設定でjupyter labにアクセスする」ですから
何もIPを固定する必要はなく、IPが変わっても常に同じURLで接続できればいいわけです。
インスタンスのIPを固定せずこれを実現するには、変化するIPアドレスに対するホスト名の対応付けを追従させればいいわけです。
これをやってくれるのが動的DNSサービスです。

例えばno-ipなんかがあります
https://www.noip.com/

下記に従って設定してみてください。
Ubuntu 16.04 に noip を入れる
https://qiita.com/ikeyasu/items/96e2ff8594ae1f8beeab

うまくいけば、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/373785/1af160c4-e0f4-4683-1515-318e43cf139a.png)
このIP/targetの欄が常に今起動しているEC2インスタンスのIPv4 パブリック IPと同じ値になり
\<hostname>:8888
にブラウザからアクセスすれば、EC2上のjupyter labにアクセスできます。

お疲れ様でした。

# ぶっちゃけた話
Sagemakerのノートブックインスタンス使うと1ボタンでできます。


# 参考
Amazon EC2 のキーペア
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html

PuTTY を使用した Windows から Linux インスタンスへの接続
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/putty.html

Jupyter事始め
https://qiita.com/taka4sato/items/2c3397ff34c440044978

no-ip
https://www.noip.com/

Ubuntu 16.04 に noip を入れる
https://qiita.com/ikeyasu/items/96e2ff8594ae1f8beeab