この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部の鈴木です。
今回はJupyterHubのDockerSpawnerで、コンテナ起動前にブートストラップを実行する方法を紹介します。
DockerSpawnerとは
DockerSpawnerは、JupyterHub Docker Spawnerの一つで、JupyterHubで認証されたユーザーを受け取り、そのユーザーのためにDockerコンテナ内にノートブックサーバーをspawnします。
c.DockerSpawner.pre_spawn_hook
を設定することで、コンテナ起動前に、例えば以下のようにブートストラップを設定することが可能です。
# DockerSpawner APIのドキュメントから引用した。(2021/10/10)
# https://jupyterhub-dockerspawner.readthedocs.io/en/latest/api/index.html
from subprocess import check_call
def my_hook(spawner):
username = spawner.user.name
check_call(['./examples/bootstrap-script/bootstrap.sh', username])
c.Spawner.pre_spawn_hook = my_hook
今回はブートストラップの例として、ユーザーごとのディレクトリがなければ作成する処理を設定してみます。
この例は、以下のIssueで取り上げられているようなケースに役立ちます。これは、Linux環境でコンテナのマウント先ディレクトリがホスト側にない場合に、Dockerがホスト側にディレクトリをJupyterLab側からアクセスできない権限で作成しているような状況です。
Permission Denied for new user volumes with custom path · Issue #160 · jupyterhub/dockerspawner
c.DockerSpawner.pre_spawn_hook
を利用することで、コンテナ起動前にディレクトリ作成を自動化できます。
前提
環境
- macOS Catalina バージョン10.15.7
- JupyterHub 1.4.2
- dockerspawner 12.1.0
- Docker version 20.10.7
やってみる
pre_spawn_hookを設定する
jupyterhub_config.pyのうち、今回設定するpre_spawn_hookに関係がある箇所を確認します。
必要な作業はとても簡単で、pythonで実行したい関数を作成し、c.Spawner.pre_spawn_hook
に設定するだけです。
今回の検証では、ディレクトリを作るだけだと、作ったのがDockerかJupyterHubか判断が付きにくかったので、ディレクトリにtest.txt
も作成するようにしました。
jupyterhub_config.pyの抜粋
# 抜粋
from pathlib import Path
import os
# JupyterHubのユーザーがコンテナから参照するディレクトリ
notebook_work = 'JupyterHub用のディレクトリ/jupyterhub-user/'
# コンテナは、参照するディレクトリの下にさらにユーザー名のディレクトリがあるとして、そこを参照する。
c.DockerSpawner.volumes = {notebook_work + "{username}" : {'bind': "/home/jovyan/work", 'mode': 'rw'}}
def create_volume_dir_hook(spawner):
""" 各ユーザー用のディレクトリがホスト側にないとき、ディレクトリを作成する。
"""
# JupyterHubからログインしたユーザーのユーザー名を受け取る。
username = spawner.user.name
user_volume_dir_path = os.path.join(notebook_work, username)
if not os.path.exists(user_volume_dir_path):
os.mkdir(user_volume_dir_path)
# 動作確認のため、作成したディレクトリに`test.txt`を作成する。
Path(os.path.join(user_volume_dir_path, "test.txt")).touch()
# ブートストラップを設定する。
c.Spawner.pre_spawn_hook = create_volume_dir_hook
動作を確認する
pre_spawn_hookを設定した設定ファイルを読み込んで、JupyterHubを起動します。
jupyterhub -f jupyterhub_config.py
hubadmin
というユーザーを作って、JupyterHubにログインしてみます。
コンテナ側からは、/home/jovyan/work
にtest.txt
があることが確認でき、pre_spawn_hookで設定した処理が実行されていることが分かります。
また、ホスト側でコンテナと共有するディレクトリに移動し、配下のディレクトリ構造を確認すると以下のようになっており、意図通りに動作していることが確認できました。
tree ./jupyterhub-user
# jupyterhub-user
# └── hubadmin
# └── test.txt
最後に
今回は、JupyterHubのDockerSpawnerで起動するコンテナを起動する前にブートストラップを実行する方法を確認しました。
コンテナ起動前に事前に実行しておきたい処理をpythonで定義できるので、とても便利ですね。