GCPで無料のJupyter Notebookサーバを立てる

こういう内容はnoteよりQiitaかなと思い、転載してみます。
https://note.com/inoccu/n/n9d5a74d2316b

Google Cloud Platform（GCP）には、Always Freeという期限のない無料枠があります。その中にはスペックはそれほどではないものの、仮想マシンが含まれており、それを使ってUbuntuサーバを立て、Jupyter Notebookサーバとして使うことにしました。

まず、GCPのAlways Freeがどのようなものか、[こちらのサイト](https://cloud.google.com/free/docs/gcp-free-tier?hl=ja)から確認してください。仮想マシンはComputing Engineというサービスになるので、その部分だけ抜き取ったのが下記の内容です。

> 1 つの非プリエンプティブル f1-micro VM インスタンス（1 か月あたり）。次の米国リージョンのいずれかで利用できます。  
オレゴン: us-west1  
アイオワ: us-central1  
サウスカロライナ: us-east1  
30 GB 月の HDD  


f1-microはどの程度のスペックかというと、CPUは仮想1コア、メモリは614MBです。たったそれだけ？と思うかもしれませんが、たったそれだけです。ただ、このマシンでUbuntuなどのLinuxで使って主に開発用、実験用のサーバ用途とするなら、決して非現実的な環境でもありません。

※ちなみに、GCPの費用はComputing Engine自体の料金以外にデータの下り送信料金があるのでご注意ください。ただ、どの程度使うかにもよりますが、月に100円も行かないのではないかと思います。

インストールの方法については説明を端折りますが、注意するべきはリージョンをきちんと指定されたものにすることと、ディスク容量はブートディスク（インストールするOSを決める）の編集画面で指定する（無料枠で最大の30GBにしましょう）ことくらいです。OSは最新のUbuntu 20.04 LTSを使うことにしました。

また、後でWebサーバを立ち上げるので、ファイアウォールの設定でHTTPトラフィックとHTTPSトラフィックを有効にしておきます。

### 日本語化

仮想マシンが立ち上がったら、メッセージなどの日本語化と、タイムゾーンをJSTに変更します。

```bash
sudo apt -y install language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8
```

ここで一旦、再起動して、次にタイムゾーンの設定です。

```bash
sudo dpkg-reconfigure tzdata
```

### スワップの設定

614MBのメモリではさすがに少ないので、スワップを設定します。1GBを設定します。

```bash
dd if=/dev/zero of=/swapfile bs=1M count=1024
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
```

これでスワップが有効になりますが、再起動後もスワップを有効にするため、/etc/fstabに下記の設定を追加します。

```
/swapfile swap swap defaults 0 0
```

### Apacheの導入

Jupyter Notebookをインストールした後、Apacheでリバースプロキシするので、まずはApacheをインストールします。

```bash
apt install apache2
```

私はさらにPHPやらMariaDBやらを入れたのですが、Jupyter Notebookとは無関係なので端折ります。（スワップが有効ならMariaDBすら使える！）

また、SSLアクセスするならLet's Encyptの設定も行います。（私もやりました。）でも、Jupyter Notebookとは直接の関係が無いので、それも端折ります･･･。

### Jupyter Notebookの導入

Anacondaだとちょっと荷が重いかなと思ったので、Minicondaを使います。Minicondaのインストールにはanyenvとpyenvを使います。

anyenvのインストールは、[こちらの公式サイト](https://github.com/anyenv/anyenv)を参考に行います。

```bash
git clone https://github.com/anyenv/anyenv ~/.anyenv
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_aliases
~/.anyenv/bin/anyenv init
```

ここで、さらに.bash_aliasesに追加する文字列が表示されるので、追加します。

シェルを再起動して、次のコマンド。

```bash
anyenv install --init
```

次は、pyenvのインストール。

```bash
anyenv install pyenv
```

pyenvを使ってMinicondaをインストールします。最新のMinicondaだとインストールが終わらない（仮想CPUが1コアだとダメらしい？）ので、miniconda3-4.6.14を使います。

```bash
pyenv install miniconda3-4.6.14
```

私はホームディレクトリの下にdevディレクトリを作って、そこでMinicondaを有効にするようにしているので、このような操作をします。

```bash
cd ~/
mkdir dev
cd dev
pyenv local miniconda3-4.6.14
```

さらにJupyter Notebookをインストールします。

```bash
pip install jupyter notebook
```

Jupyter Notebookの設定ファイルを作成し、パスワードを設定しておきましょう。

```bash
jupyter notebook --generate-config
jupyter notebook password
```

### Jupyter Notebookの自動起動

サーバとして使用するにはJupyter Notebookが自動起動する必要があります。そこで、/etc/systemd/system/jupyter.serviceというファイルを作成し、下記のようにします。{USER}と{GROUP}については、適宜置き換えてください。

```
[Unit]
Description = Jupyter Notebook
[Service]
Type=simple
PIDFile=/var/run/jupyter-notebook.pid
ExecStart=/home/{USER}/.anyenv/envs/pyenv/shims/jupyter notebook
WorkingDirectory=/home/{USER}/dev
User={USER}
Group={GROUP}
Restart=always
[Install]
WantedBy = multi-user.target
```

あとは、下記のとおり。

```bash
systemctl start jupyter
systemctl enable jupyter
```

### Apacheのリバースプロキシの設定

最後にリバースプロキシの設定を行います。今回は、https://ドメイン/notebook/のようになります。

先ほど作成したJupyterの設定ファイル（ホームディレクトリの、.jupyter/jupyter_notebook_config.py）を編集します。編集箇所のみを示します。

```text
c.NotebookApp.allow_remote_access = True
c.NotebookApp.base_url = '/notebook/'
c.NotebookApp.open_browser = False
```

Apache2のsites-available内のファイルを編集します。これも編集箇所のみ。SSLProxyEngineは、私の環境では実はSSL化しているためです。

```apache
SSLProxyEngine On
ProxyRequests Off
ProxyPreserveHost On
<Proxy https://localhost:443>
    Require all granted
</Proxy>
<Location /notebook/>
    ProxyPass http://localhost:8888/notebook/
    ProxyPassReverse http://localhost:8888/notebook/
</Location>
<Location /notebook/terminals/websocket/>
    ProxyPass ws://localhost:8888/notebook/terminals/websocket/
    ProxyPassReverse ws://localhost:8888/notebook/terminals/websocket/
</Location>
<LocationMatch /notebook/(api/kernels/[^/]+/channels.*)>
    ProxyPass ws://localhost:8888/notebook/$1
    ProxyPassReverse ws://localhost:8888/notebook/$1
</LocationMatch>
```

いくつかのApacheモジュールを有効化する必要があります。

```bash
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
```

あとはApacheの再起動を行えばOKです。

```bash
systemctl restart apache2
```

PandasやMatplotlibも問題なく動作しますので（Minicondaなので、それぞれインストールは必要ですが･･･）、興味のある方は是非試してみてください。