はじめに
Jupyter Notebookにユーザ管理機能を追加したJupyterHub(v1.0.0)を構築する方法をまとめます。
github.com
JupyterHubはデフォルトだとPAM認証なのでLinuxのユーザを作成(adduser
/passwd
)しなければなりませんし、ユーザのサインアップやパスワードの変更機能が提供されていないので実運用するには色々と難点があるんですが、あまり良い環境構築手順がなく苦労しました...。
以降ではこんなことをやります。最低限の構成としてはこれぐらいあれば良いんじゃないかと思います。
- Apacheでリバースプロキシ
- SSL対応
NativeAuthenticator
でユーザのサインアップ・承認、パスワード変更機能を追加
DockerSpawner
でNotebookサーバをDockerコンテナで生成
前提
rootに変更
$ sudo su -
Miniconda3のインストール
Anacondaでも良いです。
# wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
# bash Miniconda3-latest-Linux-x86_64.sh
...
Do you accept the license terms? [yes|no]
[no] >>> yes
Miniconda3 will now be installed into this location:
/root/miniconda3
- Press ENTER to confirm the location
- Press CTRL-C to abort the installation
- Or specify a different location below
[/root/miniconda3] >>> /opt/miniconda3
...
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] >>> yes
# source ~/.bashrc
# rm Miniconda3-latest-Linux-x86_64.sh
Conda環境の作成
Pythonは3.7にしておきます。
anaconda
に関しては、標準のSpawnerである LocalProcessSpawner
を使う場合に色々な便利ライブラリが欲しかったので指定しましたが、
結局DockerSpawner
を使うのでいらないと思います。
# conda create -n py37 python=3.7 anaconda
# conda activate py37
JupyterHubのインストール
本記事執筆時点で最新バージョンは1.0.0です。
# conda install -c conda-forge jupyterhub
NativeAuthenticatorのインストール
ユーザのサインアップ・承認、パスワード変更機能を追加するため、NativeAuthenticatorを導入します。
最新版が欲しいので直接リポジトリからインストールします。
# yum install git
# cd ~
# pip install -e git+https://github.com/jupyterhub/nativeauthenticator.git@919a37460cdb46ef536985c0cb0c1109d5e0e483#egg=jupyterhub_nativeauthenticator
# cd src/jupyterhub-nativeauthenticator/nativeauthenticator/
ただどうやら上記のバージョンだとJupyterHubのv1.0.0に対応してないらしく、パスワード変更でエラーになってしまいました。
本家にIssue作成しときましたが、とりあえずコードを直修正します。
github.com
handler.ChangePasswordHandler.post
のユーザ取得処理に await
を追加すれば問題は解消しました。
124 @web.authenticated
125 async def post(self):
126
127 user = await self.get_current_user()
DockerSpawnerのインストール
デフォルトのLocalProcessSpawner
だとLinuxユーザが存在しなければならず煩わしいので、
ユーザごとのNotebookサーバをDockerコンテナとして立ち上げるためDockerSpawnerを導入します。
# pip install dockerspawner
Dockerのインストール
Dockerがないのであればインストールします。
# yum install -y yum-utils device-mapper-persistent-data lvm2
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install -y docker-ce docker-ce-cli containerd.io
# systemctl start docker
# systemctl enable docker
Hub APIのポートを解放
Dockerコンテナからホストで動作するJupyterHubのAPIにアクセスするためFWの設定を変更します。
# firewall-cmd --add-port=8081/tcp --zone=public --permanent
# firewall-cmd --reload
設定ファイルの作成
# mkdir /etc/jupyterhub
# cd /etc/jupyterhub
# jupyterhub --generate-config
c.JupyterHub.ip = '127.0.0.1'
c.Authenticator.admin_users = {'jupyter'}
c.JupyterHub.db_url = 'sqlite:////etc/jupyterhub/jupyterhub.sqlite'
c.JupyterHub.authenticator_class = 'nativeauthenticator.NativeAuthenticator'
c.JupyterHub.hub_connect_ip = '<jupyterhub-server-ip>'
c.JupyterHub.hub_ip = '0.0.0.0'
c.JupyterHub.hub_port = 8081
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
c.DockerSpawner.hub_connect_ip = '10.0.1.4'
c.DockerSpawner.image = 'jupyter/scipy-notebook:6c3390a9292e'
notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir
c.DockerSpawner.volumes = { 'jupyterhub-user-{username}': notebook_dir }
JupyterHubサービスの設定
[Unit]
Description=Jupyterhub
[Service]
User=root
Environment="PATH=/opt/miniconda3/envs/py37/bin:/opt/miniconda3/condabin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
ExecStart=/opt/miniconda3/envs/py37/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py
WorkingDirectory=/etc/jupyterhub
[Install]
WantedBy=multi-user.target
JupyterHubを再起動します。
# systemctl enable jupyterhub
# systemctl start jupyterhub
Using a reverse proxyを参考に設定します。
<VirtualHost *:443>
ServerAdmin <server-admin>
ServerName <jupyterhub-server-hostname>
# Configure SSL
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:3DES:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile <ssl-certificate-file>
SSLCertificateKeyFile <ssl-certificate-key-file>
SSLCertificateChainFile <ssl-certificate-chain-file>
# Use RewriteEngine to handle websocket connection upgrades
RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:8000/$1 [P,L]
<Location "/">
# Preserve Host header to avoid cross-origin problems
ProxyPreserveHost on
# Proxy to JupyterHub
ProxyPass http://127.0.0.1:8000/
ProxyPassReverse http://127.0.0.1:8000/
</Location>
</VirtualHost>
再起動
# shutdown -r now
JupyterHubにアクセス
https://jupyterhub-server-hostname にアクセスし、ログイン画面が表示されることを確認します。
Adminユーザの作成
Adminユーザを作成するため、Signup!
リンクからサインアップ画面へ遷移します。
ユーザ名にはjupyterhub_config.py
のc.Authenticator.admin_users
に指定したjupyter
を入力します。
Your information have been sent to the admin
と表示されますが、Adminとして設定したjupyter
については自身がAdminなのですぐさまログインできるようになります。
Adminユーザでログイン
Login!
リンクからログイン画面へ遷移し、上記で入力したアカウント情報を用いてログインします。
一般ユーザの作成
上記の手順と同様にサインアップ画面から任意のユーザ名、パスワードでユーザを作成します。
ただし、この時点で一般ユーザはログインすることができず、Adminユーザによる承認が必要となります。
Adminユーザでログインし、/hub/authorize
にアクセスし、新規作成されたユーザを承認することでアカウントが有効になります。
パスワードの変更
パスワードの変更は/hub/change-password
から実施できます。
ユーザの管理
AdminユーザはControl Panel>Admin
からユーザの管理(Notebookサーバの停止、ユーザの削除など)を行うことができます。
ただし、Add Users
でユーザを作成してもパスワードが設定されないのでログインができません。使用しないことをおすすめします。
Jupyterノートブックの保存先
各ユーザのJupyterサーバはDockerコンテナとして立ち上がります。
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
350c3f757230 jupyter/scipy-notebook:6c3390a9292e "tini -g -- start-no…" About an hour ago Up About an hour 127.0.0.1:32911->8888/tcp jupyter-test
bb36d90c7890 jupyter/scipy-notebook:6c3390a9292e "tini -g -- start-no…" 2 hours ago Up 2 hours 127.0.0.1:32910->8888/tcp jupyter-jupyter
Jupyterノートブックは各コンテナ上の/home/jovyan/work
配下に保存されます。
# docker exec -it jupyter-jupyter bash
$ cd work/
$ pwd
/home/jovyan/work
$ ls
foo.ipynb