JupyterHubを利用して管理者が用意したPythonチュートリアル用 jupyter notebookをユーザーがブラウザからすぐに実行できる環境を構築します。
- JupyterHubによる、不特定多数のユーザーがブラウザからアクセスするだけでPythonを実行できる環境の提供
- Dockerコンテナによる、ユーザーごとに隔離された実行サーバ
- Githubによる、チュートリアル資料の管理
Pythonワークショップを楽にやりたい
近年のAIブームにより多くの企業においてPython社内教育のニーズが急激に高まっているようですが、外部サービスを利用するならともかく、Pythonによる機械学習研修やワークショップを社内で開催するというのはなかなかに面倒です。
教材を作成するのはまあよいとして、Python環境の構築でコケる人が必ず何人かは出ますし、チュートリアル教材となるjupyter notebookの配布やユーザに教材のバージョンを更新してもらうことなどは大変面倒です。
ここではそのような面倒ごとを解決するために、ユーザー側の事前準備不要で管理者の用意したJupyterNotebookを実行できる環境をJupyterHubによって提供します。
※Google ColaboratoryとGoogleCloudによるnotebookの共有機能を利用できる環境ならそっちを利用した方がはるかに楽です。
JupyterHubとは
ブラウザからアクセス/実行できるユーザ認証機能つきJupyterサーバーです。
JupyterHubは、ユーザーグループにノートブックのパワーをもたらします。ユーザーにインストールおよび保守タスクを負担することなく、計算環境とリソースへのアクセスを提供します。ユーザー(学生、研究者、データサイエンティストを含む)は、システム管理者が効率的に管理できる共有リソース上の独自のワークスペースで作業を完了できます。
JupyterHubはクラウドまたは独自のハードウェアで実行され、事前に構成されたデータサイエンス環境を世界中のユーザーに提供することができます。カスタマイズ可能でスケーラブルであり、小規模および大規模なチーム、アカデミックコース、および大規模なインフラストラクチャに適しています。
Google翻訳 from Project Jupyter | JupyterHub
主要な機能は、
ユーザ認証機能
ユーザごとのsingle jupyter notebook サーバーの生成
の2つですが、これらについてはユースケースに応じて多様なオプションが用意されています。
認証についてはLDAPやGithubアカウント認証など多くの選択肢が用意されていますし、single notebook serverの生成についてもDockerを使ったりKubernetesでリソースを管理したりといろいろあります。
今回はPythonワークショップでの使用=使い捨て環境を想定しているので、
NativeAuthenticator (ユーザー名とパスワードでアカウント作成し、管理者が許可する方式)
によってシンプルな認証管理を行い、
DockerSpawner (ユーザーごとにnotebook実行サーバをdockerコンテナで走らせる方式)
によってユーザーごとに使い捨てのnotebook実行サーバーを立ち上げる構成を採用します。
実行環境
テスト環境として
Google Cloud Platform:Compute EngineのVMインスタンスで構築します。
VMインスタンス: Ubuntu 16.04 LTS
ポート開放: TCP 22, 80, 443, 8000
環境準備
関連パッケージのインストール
はじめはpipからjupyterhubをインストールしようとしたのですがnode.jsとのバージョン依存などでハマったのでcondaの使用を推奨します。
#: Minicondaのインストール(AnacondaでもOK) $ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh $ sh Miniconda3-latest-Linux-x86_64.sh $ source .bashrc $ conda create -n jupyterhub37 python=3.7 $ conda activate jupyterhub37 #: jupyterhubと関連パッケージのインストール $ conda install -c conda-forge jupyterhub $ conda install jupyter_client $ git clone https://github.com/jupyterhub/nativeauthenticator.git $ pip install -e nativeauthenticator/ $ pip install dockerspawner
Dockerのインストール
各ユーザーのnotebook実行サーバは独立したdockerコンテナ内で走るのでdocker-CEをインストールします。 インストール方法は公式ドキュメントの通りです。
$ sudo apt-get -y update && sudo apt-get -y upgrade $ sudo apt-get remove docker docker-engine docker.io containerd runc $ sudo apt-get -y install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" $ sudo apt-get -y update $ sudo apt-get -y install docker-ce docker-ce-cli containerd.io
Notebookサーバ用Docker imageのbuild
各ユーザーのNotebook実行サーバーを走らせるためのdocker imageをbuildします。
以下の内容でDockerfileを作成し、sudo docker build -t hub/test1 .
でbuildします。
FROM jupyter/scipy-notebook USER root RUN pip install optuna keras RUN git clone https://github.com/zhiyzuo/python-tutorial.git work CMD ["jupyterhub-singleuser", "--allow-root"]
Python講習を想定しているのではじめにチュートリアル用のnotebook集をgithubからcloneしてきます。"python tutorial github "で検索して上の方にあったリポジトリをサンプルに使用しています。
また、scipy-notebookはデータサイエンスに最低限必要なライブラリしかインストールされていないので、この例ではkerasとOptunaを追加インストールしてみます。
rootに切り替えているのは、通常ユーザのままではNotebookサーバーは立ち上がるが新規notebookの作成ができないという状態になったためです。
このトラブルの対処はJupyterHub + dockerspawnerでユーザごとにマウントするボリュームを変える - Qiitaを参考にさせていただきました。
テスト実行
ここまできたらいったんテスト起動してみましょう。
$ mkdir ~/jupyterhub && cd ~/jupyterhub $ sudo jupyterhub
http;//SERVER_IP:8000へアクセスしてログイン画面が出ればOKです。
※httpsではなくhttpであることに注意。
sudo jupyterhub
でcommand not found
と言われる場合は下記リンクを参考に、visudoで/etc/sudoers
をいじりましょう。
sudo したときに「コマンドが見つかりません」と怒られた場合 - 約束の地
jupyterhub_config.pyの作成
まだバニラ状態のjupyterhubが動いただけで、認証はデフォルトのPAM認証(システムユーザー名とパスワードで認証)でありdockerも一切使用していません。
jupyterhubは起動ディレクトリ内にjupyterhub_config.py
というファイルを置くことで認証方法などの詳細な設定が可能になります。
一度起動した後の~/jupyterhub
ディレクトリを見るとjupyterhub_cookie_secret
とjupyterhub.sqlite
の二つのファイルが生成されているはずです。
このディレクトリ内にさらにjupyterhub_config.py
を下記の内容で追加しましょう。
#: 認証方法と管理ユーザ名の指定 c.JupyterHub.authenticator_class = 'nativeauthenticator.NativeAuthenticator' c.Authenticator.admin_users = {'admin'} from jupyter_client.localinterfaces import public_ips ip = public_ips()[0] c.JupyterHub.hub_ip = ip #: SSLを使うなら鍵と証明書の位置を指定 #c.JupyterHub.ssl_key = '/etc/ssl/server.key' #c.JupyterHub.ssl_cert = '/etc/ssl/server.crt' c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner' #: Jupyter labを使う c.Spawner.default_url = '/lab' c.DockerSpawner.default_url = '/lab' """ユーザーの作業ディレクトリの指定 jupyter/scipy-notebook イメージにはjovyanというユーザディレクトリがデフォルトで存在するのでそこを使用する 作業ディレクトリ(/home/jovyan/work)をdocker volumeマウントすることで作業内容が永続化されるように設定する # jovyanって誰?という疑問についてはこちらを参照 # [https://github.com/jupyter/docker-stacks/issues/358] """ notebook_dir = '/home/jovyan/work' c.DockerSpawner.notebook_dir = notebook_dir c.DockerSpawner.volumes = {'jupyterhub-user-{username}': notebook_dir} #: single notebookサーバ用dockerイメージの選択 c.DockerSpawner.container_image = 'hub/test1'
ここで改めてjupyterhubを起動します。
$ sudo jupyterhub [I 2019-11-09 08:20:02.459 JupyterHub app:2120] Using Authenticator: nativeauthenticator.nativeauthenticator.NativeAuthenticator [I 2019-11-09 08:20:02.459 JupyterHub app:2120] Using Spawner: dockerspawner.dockerspawner.DockerSpawner-0.11.1 ...
ログから設定内容が反映されていることがわかります。
http;//SERVER_IP:8000へアクセスすると、先ほどとは異なりログイン画面下に"Signup!"が追加されています。
まずは"Signup!"からユーザー登録を行いましょう。
config内で管理者に登録されているユーザーも"Signup!"からパスワードを登録する必要があります。
一般ユーザーはアカウントを作成した後、管理者の承認を受ける必要があります(やり方は後述)。
ログインするとJupyterLabが起動します。また、githubからcloneしてきた教材が初期状態で配置されていることが確認できます。
新規ユーザー承認
一般ユーザーはアカウントを作成した後、管理者の承認を受けるとログイン可能になります。
承認のためにはまず管理ユーザーでログインした状態でhttp://SERVER_IP:8000/hub/authorizeにURLの直接打ち込みでアクセスします。やや面倒ですがNativeAuthenticator
ではGUIアクセスは実装されていないっぽいです。
承認ボタンを押せば承認作業完了です。
おわりに
ブラウザからアクセスできるPythonのマルチユーザー環境は今回想定したようなワークショップ以外にも、グループでの共同開発や出先でのデモンストレーションなど様々なユースケースがあるかと思います。
公式リポジトリに様々なオプションが用意されているので用途に合わせた最高のJupyterhub環境を構築しましょう。
参考
CentOS 7にJupyterHub 1.0を導入(SSL対応/NativeAuthenticator/DockerSpawner) - hiroki-sawano's diary
JupyterHub + dockerspawnerでユーザごとにマウントするボリュームを変える - Qiita
DockerSpawnerをカスタムして細かいフォルダ共有制御を実現している例
おまけ:ログアウト
ログアウトの方法はわかりづらいのですが、"FIles"にあります。
"Hub Control Panel"からGUIアクセスできる"Admin"ダッシュボードはNativeAuthenticatorを使用している場合は飾りなので無視してください。
おまけ:Volume
dockerの基本的な話ではありますが永続化されたフォルダのvolumeは以下のように確認できます。
$ sudo docker volume ls DRIVER VOLUME NAME local jupyterhub-user-admin local jupyterhub-user-testuser1