リモートのJupyter Notebookを自動でブラウザで開く方法

2ヶ月くらい前に「現場で使える! TensorFlow開発入門 Kerasによる深層学習モデル構築手法」という書籍を買ってみたのですが手をつけずに放置してました..。サンプルコードぐらい動かそうということで環境構築をAzure上で行いました。

この本の中では nvidia-docker を使ってコンテナの中でjupyter notebookを起動するので以前にfast.ai用に作ったAzureラッパースクリプトを少し修正しました。

github.com

サンプルプログラムを動かすための環境構築は基本的に翔泳社のサイトからダウンロードできる補足資料のpdfの通りに進めれば何も問題ないです。

が、

↑のラッパースクリプトを使うとjupyter notebookのトークン認証のトークンを毎回手動でコピペして入力する必要がなくなるので毎回の立ち上げのストレスが減ります :-)

個人的にはすごい便利です。

今回はリモートマシンのdockerコンテナで起動しているjupyter notebookのトークンを取得して自動でブラウザで開く方法について書きます。

起動中のjupyter notebookのトークンを取得する

$ jupyter notebook list

で起動しているjupyter notebookのtokenつきのURLが取得できます。

具体的には以下のような出力が得られます。

Currently running servers:
http://localhost:8888/?token=1864c580501c69e7a331707d7901bc2e4263bffd54c70538 :: /notebooks

この出力から "http://localhost:8888/?token=xxx" の部分を抜き出し、localhostをリモートマシンのIPアドレスに置き換えたURLをopenコマンドで開けばokです(Macの場合)。

ちなみに、複数のjupyter notebookインスタンスを起動しているときはhttp://localhost:xxxx/?token=xxx が複数行出力されます。

dockerコンテナでjupyter notebookを動かしているとき

dockerコンテナでjupyter notebookが起動しているときはnvidia-dockerコマンドを使って

$ sudo nvidia-docker exec YOUR_CONTAINER_NAME jupyter notebook list

でjupyter notebookのtokenつきのURLが取得できます。

ここで "YOUR_CONTAINER_NAME" はjuypter notebookを起動しているdockerコンテナの名前です。

本のサンプルの場合だと、

sudo nvidia-docker run --rm --name tfbook -p 80:8888 -p 6006:6006 -v /notebooks:/notebooks tfbook

というようにtfbookというコンテナ名で jupyter notebookを起動しています。 (--nameで指定しているtfbookがコンテナ名で末尾のtfbookはdockerイメージ名)

このコマンドだと明示的にjupyter notebookを起動していませんが 大元のDockerfileの中で定義されています。

CMD ["/run_jupyter.sh", "--allow-root"] # 最終行

この1行があるのでコンテナ生成時にjupyter notebookが起動します。

ちなみに、nvidia-docker runだと空の出力になってしまいます。

nvidia-docker execを使って既存のコンテナ上でjupyter listコマンドを実行することがポイントです。

リモートマシンのjupyter notebookのトークンを取得

リモートマシンで先のコマンドを実行するにはsshコマンドを使います。

最近まで知らなかったのですが(汗)、ssh ユーザー名@リモート端末のIPアドレス 任意のコマンド とするとリモートマシン上で任意のコマンドを実行できます。

なので、今回の場合、以下のようなコマンドになります。

ssh -i ${privateKeyPath} ubuntu@${instanceId} 'sudo nvidia-docker exec tfbook jupyter notebook list'`

あとは このコマンド出力からtokenつきのURLの箇所を抜き出して、localhost をリモートマシンのIPアドレスに置換してブラウザに渡せばokです。

完成形スクリプト

最終的には以下のシェルスクリプトを実行することによってリモートマシン上で起動しているjupyter notebookを自動的にブラウザで開くことができます。

list=`ssh -i ${privateKeyPath} ubuntu@${instanceId} 'sudo nvidia-docker exec tfbook jupyter notebook list'`
url=`echo $list | grep http | sed -e "s/localhost/${instanceId}/g" | sed -e "s/:8888//g" | awk '{print $4}'`
echo $url
open $url

また、リモートマシンに明示的にログインせずにリモートマシン上でjupyter notebookを起動するには、同様にして

ssh -i ${privateKeyPath} -o "StrictHostKeyChecking no" ubuntu@${instanceId} "sudo nvidia-docker run --rm --name tfbook -p 80:8888 -p 6006:6006 -v /notebooks:/notebooks tfbook"

となります。

docker使わない場合は、もっとシンプルに

ssh -i ${privateKeyPath} -o "StrictHostKeyChecking no" ubuntu@${instanceId} "cd /path/to/notebook_dir; jupyter notebook"

です。