はじめに
開発メンバーが増えたので、jupyterhubを立ち上げてユーザーごとにjupyterlabできるようにしようかな、と。これは、作業の備忘録です。
参考
いつものとおり、Qiita先輩方の情報で本件対応させていただきます。参考サイトは次のとおりです。場合によってはこの記事を読むよりも、以下を直接読んだ方がいいかもしれません。しかし、情報が古く最新の環境にマッチするかどうか保証できません。
参考(1)
参考(2)
参考(3)
この記事では、2024年3月の jupyterhub/jupyterhub Doecker Hub の latestイメージをベースにして環境構築します。
概要
(1)公式の docker を取得し、コンテナに入って
(2)カスタマイズ設定し、
(3)コミットして専用コンテナを作る。
作業開始
公式の dockerを取得し、コンテナに入る
取得して、bashでコンテナ内に入っちゃいます。(ポート番号は、利用中のポートと被らないよう適当に設定)
docker run -it -p 8069:8000 --name jupyterhub-xxx jupyterhub/jupyterhub bash
コンテナに入ってカスタマイズ
必要パッケージのインストール
jupyterhub コンテナに入ると、rootユーザーでコマンド操作できます。以下、rootユーザーで実行する前提での記述になっています。
参考(1)とは異なり、apt に libnode64 なんて存在しないそうです。
apt update
apt upgrade
apt install python3 python3-pip npm nodejs vim git iputils-ping net-tools wget curl python3-dev python3-pip python3-venv python3-pycurl build-essential cmake clang libaio1 libffi-dev libfreetype-dev libpq-dev
apt install -y --no-install-recommends fonts-noto-cjk
apt autoremove -y && apt clean && rm -rf /var/lib/apt/lists/*
このコマンドでインストールされるnodejsは12.22です。このままでは、この後のnpmコマンドで「(古くて)サポートされていないnodejsバージョンですので使えません」みたいなメッセージがでていろいろインストールできない場合があります。まず、nvmをインストール、nvmを使ってnodejsのバージョンアップを行いましょう。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
ターミナルをいったん閉じて開きなおします。(インストールされた環境変数を適用させます。)
nvm install Iron
そして、デフォルトで使うnodejsをver.20と指定します。
nvm use 20
次に、npm をアップデートします。
npm install npm -g
さて、これで参考(1)にある次の npm install が実行できます。
npm install -g configurable-http-proxy
python3 -m pip install --upgrade jupyterhub notebook jupyterlab
python3 -m pip install netifaces
村人第一号と村長を登録(ユーザー第一号と管理者ユーザー、ね)
(ユーザー情報の追加)
村人: testuser01
村長: testadmin
adduser testuser01
mkdir -p -m 777 /home/testuser01/notebook
chown testuser01: /home/testuser01/notebook
adduser testadmin
mkdir -p -m 777 /home/testadmin/notebook
chown testadmin: /home/testadmin/notebook
参考サイト(2)に倣って、sudoコマンドのインストールをします。
apt install sudo -y
管理者ユーザー(村長)のアカウントをsudoグループに追加します。
gpasswd -a testadmin sudo
jupyterhub_config.py (jupyterhub設定ファイル)の作成
参考サイト(2)の「jupyterhubの設定」を参考に、PAMAuthenticatorを使用したユーザー管理機能を構築します。
まず、設定ファイルの保管場所を確保。
mkdir -p /etc/jupyterhub && mkdir -p /etc/jupyter
作業フォルダをこの場所に移します。
cd /etc/jupyterhub
jupyterhubの画面上でユーザーを追加する時に実行するスクリプトを作ります。ユーザー名を画面から入力するとsudoグループに追加されたユーザーが追加されます。
シェルの変数で、パスワードは固定設定にしてます。各ユーザーはログイン後に独自のパスワードに変更してもらう・・・のかな?
cat << 'EOF' > /etc/jupyterhub/add_user.sh
#!/bin/bash
USERNAME="${1}"
PASSWORD="password"
# ユーザー追加、パスワード固定
useradd -s /bin/bash -m ${USERNAME} && echo -e "${PASSWORD}\n${PASSWORD}" | passwd ${USERNAME}
# sudoグループに追加
gpasswd -a ${USERNAME} sudo
mkdir /home/${USERNAME}/notebook
chmod 007 /home/${USERNAME}/notebook
EOF
このファイルの実行権限変更しておきます。
chmod 775 /etc/jupyterhub/add_user.sh
次のコマンドでjupyterhub_config.pyを作成します。
jupyterhub --generate-config
作成されたjupyterhub_config.pyは、コマンドを実行したフォルダにあります。
このファイルを開いて、以下の行を編集します。先にaptでインストールしたvim コマンドで作成されたコンフィグファイルを開きます。
vim jupyterhub_config.py
コンフィグファイルに設定対象行が用意され、コメントアウトされています。
先達の以下の情報を参考に、以下を設定編集します。
(1)ログイン後に'/lab'に遷移する設定
(2)各ユーザーのノートブック格納ディレクトリ指定
(3)adminユーザー名
(4)その他
デフォルトだと認証にはPAMAuthenticatorを使用するようになっていて、OSのユーザ&パスワードでログインするようになっているとのことなので、(3)、(4)は既存のユーザー情報(村人、村長)を利用しましょう。
# ログイン後に http://...:8000/user/<username>/lab? へ遷移する設定(Jupyterlabが起動)
c.Spawner.default_url = '/lab'
# Jupyterlabで作成されたノートブックファイルなどが格納されるディレクトリ
c.Spawner.notebook_dir = '~/notebook'
# adminユーザのユーザ名
c.Authenticator.admin_users = {'testadmin'}
c.LocalAuthenticator.create_system_users=True
c.LocalAuthenticator.add_user_cmd=['/etc/jupyterhub/add_user.sh']
c.PAMAuthenticator.admin_groups = {'sudo'}
次のコマンドでnotebookコンフィグのファイルを /etc/jupyter に保存します。
cat << 'EOF' > /etc/jupyter/jupyter_notebook_config.py
# 30日 非アクティブのJupyterサーバーのシャットダウン期限
c.NotebookApp.shutdown_no_activity_timeout = 30 * 24 * 60 * 60
# 3日 カーネルのシャットダウン期限
c.MappingKernelManager.cull_idle_timeout = 3 * 24 * 60 * 60
# 1時間 シャットダウンするかどうかの確認インターバル
c.MappingKernelManager.cull_internal = 60 * 60
EOF
ログ動作の設定
jupyterhubのログファイル保存ディレクトリ作成
mkdir -p /var/log/jupyterhub
ログローテーションを仕掛けます。ローテーション頻度は各環境に合わせて調整してください。
cat << 'EOF' > /etc/logrotate.d/jupyterhub
/var/log/jupyterhub/jupyterhub.log {
rotate 12
monthly
compress
missingok
notifempty
}
EOF
自動起動の設定はできなかった
JupyterHub の起動をコマンドラインで毎回やるのは面倒なので、systemd に登録して service コマンドで起動できるようにしたかったんですが・・・。Dockerでは、systemctlによる管理ができないそうです。
一応、以下のように /etc/systemd/system/jupyterhub.service ファイルを作成することで、他のサーバープロセスなどのように service jupyterhub start で起動できるようにしてみたものの、エラーが出て実行できませんでした。
cat << 'EOF' > /lib/systemd/system/jupyterhub.service
[Unit]
Description=Jupyterhub
After=syslog.target network.target
[Service]
User=root
ExecStart=/usr/local/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py --port 8069 --ip 0.0.0.0 >> /var/log/jupyterhub/jupyterhub.log 2>&1
[Install]
WantedBy=multi-user.target
EOF
ln -s /lib/systemd/system/jupyterhub.service /etc/systemd/system/jupyterhub.service
systemctl daemon-reload # config.ファイルを再読み込み
systemctl enable jupyterhub.service # 起動時にjupyterhub.serviceを自動起動
systemctl start jupyterhub.service # jupyterhub.serviceをマニュアル起動
systemctl status jupyterhub.service #jupyterhub.serviceの状態を確認。
設定終了
ここまでで、いったんDockerコンテナを commit しましょう。
docker コンテナのシェルから exit して、OSのシェルで次のdockerコマンドを実行。
docker commit <コンテナID> jupyterhub-xxx:0.0.1
docker コンテナを停止します。
docker stop <コンテナID>
jupyterhub をログファイル出力しながら起動させる
では、作成、commit した新コンテナでjupyterhubを起動しましょう。
まず、コンテナの起動。
docker run -it -p 8069:8000 --name jupyterhub-xxx
docker attach などでコンテナに入り、コンテナのシェルで次を実行。
jupyterhub -f /etc/jupyterhub/jupyterhub_config.py >> /var/log/jupyterhub/jupyterhub.log 2>&1
アクセス成功すれば終了
そして、シェル操作を離れて、Webブラウザを用いて Host(ポート番号8069)にアクセス。
Sigin in してみます。うまくいきました。
(スクリーンショットは載せません)
今後
ユーザーの新規登録、利用開始の動作も確認しなくては・・・
Dockerで構築することのうまみがよくわからない。各ユーザーのnotebookがコンテナイメージの中に全部入っているので、バックアップをとるところまで面倒みるのならば簡単というところか。
管理者はときどきcommitしてコンテナイメージをどこかにコピーする、って使い方かな。