docker
centos7
Jupyter

サーバーのDockerで起動したJupyter Notebookを他のパソコンからアクセスできるようにした話

概要

こちらの記事でCentOS7.4をインストールしたパソコンにDockerでJupyter Notebookを起動できるようにし、
それを他のパソコンからアクセスできるようにしたときの作業を備忘録としてまとめておきます。

環境

Z230 Workstation OS: CentOS7.4 (Jupyter Notebookをインストールするパソコン)
Docker version 17.09.0-ce, build afdb6d4 (Jupyter Notebookをインストールするパソコンにインストールされている)
Mac mini (Late 2014) OS: High Sierra (Jupyter Notebookのユーザー側のパソコン)

仕様

  • Jupyter NotebookをインストールするサーバーとユーザーのパソコンはLANで接続されている。
  • サーバーは職場からしかネットワークでアクセスできない(グローバルIPがない、と言う説明でいいのかな?)。
  • サーバーのJupyter Notebookには最低限のセキュリティとしてパスワードの設定だけする。
  • サーバーのJupyter Notebookには複数人がアクセスする(こういう前提でJupyter Notebookは作られてないっぽい?)
  • 仮想環境を破棄してもデータが残るようにマウントするフォルダを設定する

という前提条件で話を進めていきます。
記事を参考に同じ作業をしたい場合は(特にセキュリティなど)適宜変更してください。
なお、この記事の作業を行うときは自己責任でお願いします。

作業

1. ポートを解放する

以降の作業はSSH接続ができるならユーザー側のパソコンからSSH接続をして作業を進めてもらってかまいません。

サーバーのJupyter Notebookにアクセスするためにポートを解放します。
Jupyter Notebookではデフォルトでは8888が使われるので今回同様に8888を採用しました。

sudo firewall-cmd --add-port=8888/tcp --zone=public --permanent

こちらでポート8888を解放できます。CentOS7からfirewallの設定が楽になったなと思っています。

続けて

sudo firewall-cmd --reload

でfirewallを再起動しましょう。

sudo firewall-cmd --list-all --zone=public

ports: 8888/tcpと表示されていたら正常に解放されています。

2. Docker imageのダウンロードおよびコンテナの作成

Jupyter NotebookのDocker imageをダウンロードします。
今回は例としてjupyter/datascience-notebookを使うことにしますが、
公式のjupyterが公開しているDocker imageやそれらをベースとしているDocker imageなら同じ作業が可能だと思います。
Docker imageを変更したい場合は適宜以降の作業のjupyter/scipy-notebookの箇所を変更したDocker imageに変更してください。

実際、私は日頃ケモインフォマティクスと呼ばれる分野の解析のための
Docker imageとして用意されているchemowakate/tutorial-7thを用いています。

さて、話を戻して以下のコマンドを実行するとDocker imageがダウンロードされ仮想環境であるコンテナが作成されます。

docker create jupyter/scipy-notebook

3. パスワードを設定する

パスワード設定するためにはipythonが実行できる環境である必要があります。

3.1 サーバーですでにipythonが実行できる

サーバーでipythonが実行できるならそのままipythonと入力して以下の作業を実行してください。

3.2 サーバーでipythonが実行できない

ipythonが実行できなくても2でダウンロードしてきた仮想環境内でipythonが実行できますので安心してください。
そのような場合は
docker run -it --rm jupyter/scipy-notebook /bin/bash
ipythonが実行できる仮想環境を起動し、仮想環境内に入ります。
そしてipythonと実行しましょう。

いずれかの方法でipythonを実行した前提で話を続けていきます。

from notebook.auth import passwd
passwd()

と実行すると、パスワードの入力待ちになります。

パスワードとして入力したい文字列を入力しEnterを押すと例えば以下のような暗号化された文字列が画面に表示されます。
今後その文字列を使うのでメモ帳などに保存しておいてください。

sha1:4daaadded8f2:6d42d26960204e16891c7aba6725edbd52fe4b12
(あくまで一例です)

これ以降はipythonは使用しないのでexit()で終了してください。
仮想環境内でipythonを実行した場合はさらにexitで仮想環境も終了しましょう。

4. マウントするフォルダおよびjovyanユーザーの作成

Dockerで用意した仮想環境を破棄してしまうと仮想環境内のデータはすべて消えてしまいます。
そうなるとせっかく解析したデータなどもすべて消えてしまうのでサーバー内のフォルダをマウントしておきましょう。
これにより仮想環境内で保存したファイルなどはサーバーのそちらのフォルダにも反映されるので仮想環境を破棄してもデータが消えなくなります。

今回は複数人がJupyter Notebookを扱うことを前提に進めていきます。
その際、Jupyter Notebookを実行中に作成し、保存するファイルの所有者はjovyanと言うグループに所属するjovyanと言うユーザーとします。
こちらはご自身の用意したい環境ごとに適宜変更してください。

ちなみにjovyanJupyter Notebookを使うみんな的な意味があるそうです。
参考:Who is jovyan? #358

4.1 jovyanグループの作成

例えばgid=8888のjovyanと言うグループを作成するには以下のように実行します。

sudo groupadd -g 8888 jovyan

4.2 jovyanユーザーの作成

さらにグループjovyanに所属しているuid=8888のユーザーjovyanを作成するには以下のように実行します。

sudo useradd -g jovyan -u 8888 jovyan

と属しているグループを確認するとdockerに属しているのがわかります。

後で必要になるのでidcat /etc/groupでグループのgidを確認しておいてください。

id jovyan
uid=8888(jovyan) gid=8888(jovyan) groups=8888(jovyan)

私のパソコンではユーザーjovyanはuid=8888, jovyanグループのgidは8888に設定されています。

4.3 jupyterフォルダの作成

今回はマウントするフォルダは/jupyterにしてみました。
こちらも場所を変えたい場合は適宜変更してください。

sudo mkdir /jupyter

4.4 フォルダの権限の変更

フォルダの所有者:グループをjovyan:jovyanに変更し、所有者は読み、書き、実行すべてできるようにしておきましょう。

sudo chown jovyan/jovyan /jupyter
sudo chmod 775 /jupyter
ls -ld /jupyter
drwxr-xr-x.   2 jovyan jovyan    6 11月 28 13:44 jupyter

4+α 自分のみがJupyter Notebookを利用するなら

自分のみJupyter Notebookを利用し、マウントするフォルダも例えば/home/yamasakih/jupyterなどの自分のホームディレクトリ以下なら、
4.1, 4.3を行う必要はありません。
id 自分のユーザー名で表示されるuid, gidを用いて5の作業を行ってください。

id $USER
uid=1000(yamasakih) gid=1000(yamasakih) groups=1000(yamasakih),10(wheel),994(docker)

5. 仮想環境を起動する

最後に以下のように実行し、仮想環境を起動します。

docker run -e GRANT_SUDO=yes -e NB_UID=8888 -e NB_GID=8888 -d -p 8888:8888 --rm -v /jupyter:/home/jovyan/work --user root --name jupyter-notebook jupyter/scipy-notebook start-notebook.sh --NotebookApp.password='sha1:4daaadded8f2:6d42d26960204e16891c7aba6725edbd52fe4b12'

長いので改行してみます。

docker run -e GRANT_SUDO=yes -e NB_UID=8888 -e NB_GID=8888 -d -p 8888:8888 \
    --rm -v /jupyter:/home/jovyan/work --user root --name jupyter-notebook \
    jupyter/scipy-notebook start-notebook.sh --NotebookApp.password='sha1:4daaadded8f2:6d42d26960204e16891c7aba6725edbd52fe4b12'

各オプションを説明すると

  • -e GRANT_SUDO=yes
    仮想環境内でjovyansudoを実行できるようにしています。
  • -e NB_UID=8888
    uid=8888として実行する。マウントしたフォルダにデータを保存するときも所有者がuid=8888となります。
    今回はユーザーjovyanのuidが8888なので-e NB_UID=8888としています。

  • -e NB_GID=8888
    gid=8888として実行する。マウントしたフォルダにデータを保存するときもグループがgid=8888となります。
    今回はグループjovyanのgidが8888なので-e NB_GID=8888としています。

  • -d
    仮想環境がバックグラウンドで実行されます。

  • -p 8888:8888
    ホスト上にコンテナのポートを割り当てます。

  • --rm
    仮想環境をdocker stopで終了したとき自動で破棄されるようにします。
    マウントされているフォルダに保存しているデータは残ります。

  • -v /jupyter:/home/jovyan/work
    ホスト側の/jupyterフォルダを仮想環境内の/home/jovyan/workフォルダにマウントします。
    これによりJupyter Notebook内の/home/jovyan/workフォルダ下にデータを保存すると
    /jupyterに保存されるようになります。

  • --user root
    仮想環境内のユーザーをrootとして仮想環境を実行します。
    -e GRANT_SUDO=yes, -e NB_UID=8888, -e NB_GID=8888を設定するために必要です。
    (ただしデフォルトでrootだった気もするので省略しても良いと思います)

  • --name jupyter-notebook
    作られる仮想環境のコンテナの名前をjupyter-notebookにしています。
    docker stopで仮想環境を終了するとき少しだけ楽なので設定しています。

  • jupyter/datascience-notebook
    実行する仮想環境を指定しています。お好みのJupyter Notebookに合わせて変更してください。

  • start-notebook.sh
    仮想環境起動時に実行するスクリプトを指定しています。
    start-notebook.shを指定することで仮想環境内でJupyter Notebookが自動で起動するようになっています。

  • --NotebookApp.password='sha1:4daaa〜'
    start-notebook.shに与えている引数です。起動したJupyter Notebookにログインするためのパスワードを設定しています。
    3で決めたパスワードを暗号化したものをsha1:も含めてこちらに入力してください。

オプションを詳しく確認したい際はこちらをご覧ください。
jupyter/docker-stacks/tree/master/base-notebook

上記のコマンドを実行し、2〜3分待つとJupyter Notebookが起動します。
サーバーのIPアドレスをip addressなどで確認し、
http://xxx.xxx.xxx.xxx:8888にユーザー側のパソコンからアクセスするとJupyter Notebookへのログイン画面が表示されます。
(xxx部分はサーバーのIPアドレス)

image.png

パスワード入力欄に3で設定したパスワードを入力しエンターを押すとログインできます。
(sha1:4daaa〜の方でなく暗号化前の文字列を入れましょう)

image.png

5+α 正常に起動しない場合

なかなか起動しない場合は-dオプションを外して実行し、ターミナルに処理が表示されるようにすると良いと思います。
私のパソコンの場合Set jovyan UID to: 8888というところがすごい時間がかかります。

[yamasakih@localhost /]$ docker run -e GRANT_SUDO=yes -e NB_GID=8888 -e NB_UID=8888 -p 8888:8888 --rm -v /jupyter:/home/jovyan/work --user root --name jupyter-notebook jupyter/scipy-notebook start-notebook.sh --NotebookApp.password='sha1:4daaadded8f2:6d42d26960204e16891c7aba6725edbd52fe4b12'
Set username to: jovyan
usermod: no changes
Set jovyan UID to: 8888
Set jovyan GID to: 8888
Granting jovyan sudo access
Execute the command: jupyter notebook --NotebookApp.password=sha1:4d295dded8f2:6d42d26960204e16891c7aba6725edbd52fe4b29
[I 06:27:05.150 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret
[W 06:27:05.418 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 06:27:05.441 NotebookApp] JupyterLab alpha preview extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab
[I 06:27:05.444 NotebookApp] Serving notebooks from local directory: /home/jovyan
[I 06:27:05.444 NotebookApp] 0 active kernels
[I 06:27:05.444 NotebookApp] The Jupyter Notebook is running at:
[I 06:27:05.444 NotebookApp] http://[all ip addresses on your system]:8888/
[I 06:27:05.444 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

このような画面になればJupyter Notebookが正常に準備されている状態です。
このような画面にならない場合はオプションが正しく入力されているか確認しましょう。

6. 仮想環境の終了

仮想環境の終了は以下のコマンドでできます。

docker stop jupyter-notebook

jupyter-notebookの部分は5でオプション--nameで指定したものに適宜変更してください。

オプション-dをつけなかった場合はターミナル上でCtrl + Cを押すと

[I 06:27:05.444 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
^C
Session terminated, terminating shell...[I 06:34:13.592 NotebookApp] Interrupted...
[I 06:34:13.592 NotebookApp] Shutting down 0 kernels
 ...terminated.

と表示され終了します。

いずれの場合もオプション--rmを設定しているので終了すると同時に破棄されます。

stop前
[yamasakih@localhost /]$ docker ps -a
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                    NAMES
af262558dfb4        jupyter/scipy-notebook   "tini -- start-not..."   3 minutes ago       Up 3 seconds        0.0.0.0:8888->8888/tcp   jupyter-notebook

ちゃんと破棄されているので何も表示されません。

stop後
[yamasakih@localhost /]$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

最後に

以上でサーバーのDockerで起動したJupyter Notebookを他のパソコンからアクセスできるようにした話を終わります。
備忘録としてまとめましたが、同じ作業をしようとしている方の手助けになれば幸いです。
DockerやJupyter Notebookを使いこなして解析ライフを楽しみましょう!

参考

最後に参考にさせていただいた記事を掲載いたします。ありがとうございました。
CentOS7にJupyter Notebookを導入 (4.3, 4.4の項を参考にしました)
Linuxにユーザーを追加する
jupyter/docker-stacks/tree/master/base-notebook (オプションの設定を確認しました)