Jupyter notebookをApache2によるプロキシ経由のリモートサーバで実行する

提供: Akionux-wiki
Share/Save/Bookmark
移動先: 案内検索

概要

ブラウザからプログラミングして、結果を表示できるようなインタラクティブWebインターフェースを提供してくれるiPython notebookやSageMath notebookを以前から利用していたが、いつの間にかJupyterというのに統合されて40種類以上のプログラミング言語に対応しているようだ。 ただし、Jupyterをインストールした時点ではカーネル(各プログラミング言語に対応する)はIPythonのみインストールされていて、他の言語は個別に追加する必要があるようだ[1]

ここでは、Jupyterをインストールして、Jupyter notebookをリモートサーバで実行し、さらにApache2のプロキシを経由することで、専用のサブドメインの設定およびHTTPSのポートを使ってのアクセスができるようにして使ってみる。

テスト環境

Slackware Linux x86_64 14.1

インストール

公式のインストール方法[2]に従う。

Python 2の環境を主に使っているので、pipでインストールする

pip install jupyter

インストールは成功したが、ipythonはアンインストールされた。

パスワードをかける

パスワードを生成する手順[3]。 まずデフォルトの設定ファイルを生成する

jupyter notebook --generate-config

これで、デフォルトの設定ファイル~/.jupyter/jupyter_notebook_config.pyが生成される。

次に、jupyter-consoleでsha1鍵を生成する:

% jupyter-console 
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password: 
Verify password: 
Out[2]: 'sha1:<生成されたsha1鍵>'
In [3]: quit()

Out[2]の出力が必要なので、メモしておく。

~/.jupyter/jupyter_notebook_config.pyの必要な部分を編集する

# 先ほど生成したsha1鍵でパスワードを設定
c.NotebookApp.password = u'sha1:<生成されたsha1鍵>'

# 起動時にブラウザを開かないようにする
c.NotebookApp.open_browser = False

# 全てのIPから接続を許可する('*')か、リスンするIPアドレスを指定する
c.NotebookApp.ip = '*'

# ポート番号を指定
c.NotebookApp.port = 8888

Apache2のプロキシを経由させる

IPアドレスではなくて(サブ)ドメインでJupyter notebookを動かしたいので、Apache2(ここではバージョン2.4)のプロキシを経由させる。

[4]

ここでは例として、jupyternb.example.comというドメインのルートディレクトリからlocalhost:8888で動くJupyter notebookへリバースプロキシすることとする。

/etc/httpd/httpd.confで各プロキシのモジュールが読み込まれていることを確認する[5][6]

LoadModule proxy_module lib64/httpd/modules/mod_proxy.so
LoadModule proxy_http_module lib64/httpd/modules/mod_proxy_http.so
LoadModule proxy_wstunnel_module lib64/httpd/modules/mod_proxy_wstunnel.so

web socketのプロキシモジュールが必要なことに注意する。

Slackwareの場合は/etc/httpd/extra/httpd-vhosts.confを編集し、バーチャルホストの設定を例えば次のようにする[6]

# jupyternb notebook proxy
<VirtualHost *:443>
ServerName jupyternb.example.com

ProxyRequests Off
ProxyPreserveHost On

##############################################################
# Stuff to make the notebook secure. Copied from default-ssl #
##############################################################
SSLEngine on
SSLCertificateFile "/etc/letsencrypt/live/example.com/cert.pem"
SSLCertificateKeyFile "/etc/letsencrypt/live/example.com/privkey.pem"
SSLCertificateChainFile "/etc/letsencrypt/live/example.com/chain.pem"
BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
####################
# END OF SSL STUFF #
####################

DocumentRoot /
<Location />
    RequestHeader unset Accept-Encoding
    ProxyPass        http://localhost:8888/
    ProxyPassReverse http://localhost:8888/
    ProxyPreserveHost on
    Require all granted
</Location>
<Location /api/kernels/>
    ProxyPass        ws://localhost:8888/api/kernels/
    ProxyPassReverse ws://localhost:8888/api/kernels/
</Location>

   ErrorLog /var/log/httpd/jupyternb.example.com-error_log
   CustomLog /var/log/httpd/jupyternb.example.com-access_log common

   # Possible values include: debug, info, notice, warn, error, crit,
   # alert, emerg.
   LogLevel warn
</VirtualHost>

なお、ここではLet's Encryptで取得したSSL鍵を使うようにしている。

あとは、Apache2を再起動しておく。

sudo /etc/rc.d/rc.httpd restart

実行

設定ファイル~/.jupyter/jupyter_notebook_config.pyを作ったユーザで

jupyter notebook

を実行し、URL(先ほどの例だとhttps://jupyternb.example.com/)を開いてパスワードを入力すればJupyter notebookが使えるはずである。 ただし、この方法だとターミナルを使うことができなかった。個人的にはターミナルを使う必要はないので問題ない。

起動スクリプトを作れば簡単に起動できる。

start-stop-daemonを使った起動スクリプトの例:

#!/bin/bash
 
### BEGIN INIT INFO
# Provides:          jupyter notebook
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts jupyter notebook server
# Description:       starts jupyter notebook server by start-stop-daemon
### END INIT INFO
 
# configuration
SSD="/sbin/start-stop-daemon"
USER="jupyteruser"
GROUP="jupyteruser"
NAME="jupyter"
JUPYTERNB_HOME="/home/jupyteruser"
JUPYTERNB_CONFIG="$JUPYTERNB_HOME/.jupyter/jupyter_notebook_config.py"
JUPYTERNB_OPTS="notebook --config $JUPYTERNB_CONFIG"
JUPYTER="/usr/bin/jupyter"
PIDFILE="/run/jupyternb.pid"
 
jupyternb_start() {
        echo "Starting Jupyter notebook..."
        $SSD --start --chuid $USER:$GROUP --make-pidfile --pidfile $PIDFILE --chdir "$JUPYTERNB_HOME" --background --exec $JUPYTER -- $JUPYTERNB_OPTS
}
jupyternb_stop() {
        echo "Stopping Jupyter notebook..."
        $SSD --stop --user $USER --pidfile $PIDFILE
}
case $1 in
        start)
                jupyternb_start
                ;;
        stop)  
                jupyternb_stop
                ;;
        restart)
                jupyternb_stop
                sleep 5
                jupyternb_start
                ;;
        *)
                echo "Use: $0 {start|stop|restart}"
                exit 1
                ;;
esac
exit 0

jupyteruserを適当なユーザ・グループに書き換える。

start-stop-daemonは本来Debian系ディストリビューションのツールだが、SlackwareでもSlackBuildsのGitリポジトリ内のdevelopment/dpkgをインストールすることでstart-stop-daemonが使える。

/etc/rc.d/rc.jupyternbに配置し、実行権限を与える。 さらに、/etc/rc.d/rc.localに次の行を追加すればマシン起動時に起動させられる。

# Start jupyter notebook
if [ -x /etc/rc.d/rc.jupyternb ]; then
  /etc/rc.d/rc.jupyternb start
fi

カーネルの追加

Jupyterをインストールすると最初からIPythonのカーネルがインストールされているが、カーネルは追加できる。

IPython以外のカーネル(R, Ruby, Haskellなど)については次を参照。

References

  1. IPython kernels for other languages · ipython/ipython Wiki https://github.com/ipython/ipython/wiki/IPython-kernels-for-other-languages
  2. Installing Jupyter Notebook — Jupyter Documentation 4.1.1 alpha documentation http://jupyter.readthedocs.io/en/latest/install.html
  3. Jupyter notebookをリモートサーバで実行する - Qiita http://qiita.com/joemphilips/items/de5d12723b9b88b5b090
  4. Nginx + notebook issue · Issue #625 · jupyter/notebook https://github.com/jupyter/notebook/issues/625#issuecomment-157484914
  5. Apache 2.4 で リバースプロキシの設定 - Qiita http://qiita.com/gingi99/items/83c1fb07644cd232d91e
  6. 6.0 6.1 Nginx + notebook issue · Issue #625 · jupyter/notebook https://github.com/jupyter/notebook/issues/625#issuecomment-157484914