ページ内コンテンツ
DockerSpawner
- https://github.com/jupyterhub/dockerspawner.git
- サーバでユーザ毎に Docker でNoteBook コンテナを起動して接続.
- 作業ホームは /home/jovjan/work 固定(多分 Docker Image固定)
- see also SystemUserSpawner
Install
(jupyterhub) # pip --no-cache-dir install git+https://github.com/jupyterhub/dockerspawner.git or (jupyterhub) # pip install dockerspawner
- pip --no-cache-dir install git+https://github.com/jupyterhub/dockerspawner.git をお勧め
jupyterhub-sigleuser
- docker pull jupyterhub/singleuser
Dockerfile を使う方法
# vi Dockerfile # cp (何処か)/start.sh . # docker build -t jupyter_single-test . # docker images
- Dockerfile
FROM jupyterhub/singleuser USER root COPY start.sh /usr/local/bin RUN apt-get update \ && apt-get install -y --no-install-recommends \ vim \ && apt-get -y clean \ && rm -rf /var/lib/apt/lists/*
Docker commit でイメージを作ると,二重引数の問題が発生
- iseki でログイン時
# docker exec -it jupyter-iseki /bin/bash cd /home/ mv iseki jovyan mkdir student cd teacher/iseki cp ./back_orign cp start.sh /usr/local/bin exit # docker commit jupyter-iseki new-image
- back_orign
1 #!/bin/bash 2 cp group /etc/group 3 cp group /etc/group- 4 cp passwd /etc/passwd 5 cp passwd /etc/passwd- 6 cp /etc/gshadow- /etc/gshadow 7 cp /etc/shadow- /etc/shadow 8 cp /etc/subgid- /etc/subgid 9 cp /etc/subuid- /etc/subuid
start.sh(改), start.sh(オリジナル)
- コンテナ内の /usr/local/bin/start.sh
- コンテナ内の環境設定スクリプト
- 利用できる環境変数
SHELL=/bin/bash USER_ID=10015 MINIFORGE_VERSION=4.9.2-0 HOSTNAME=58f17edda0c7 LANGUAGE=en_US.UTF-8 JUPYTERHUB_API_TOKEN=d8137932ac144ebaa70bb04ba359fbac JUPYTERHUB_BASE_URL=/ NB_UID=10015 PWD=/home/teacher/iseki NB_NOTEDIRX=/home/{groupname}/{username}/work GRANT_SUDO=yes JUPYTERHUB_SERVER_NAME= HOME=/home/teacher/iseki LANG=en_US.UTF-8 JPY_API_TOKEN=d8137932ac144ebaa70bb04ba359fbac NB_GID=10001 CHOWN_HOME=yes JUPYTERHUB_SERVICE_PREFIX=/user/iseki/ JUPYTERHUB_OAUTH_CALLBACK_URL=/user/iseki/oauth_callback NB_GROUP=teacher USER=iseki SHLVL=1 CONDA_DIR=/opt/conda JUPYTERHUB_API_URL=http://172.22.1.75:8081/hub/api JUPYTERHUB_CLIENT_ID=jupyterhub-user-iseki JUPYTERHUB_HOST= CONDA_VERSION=4.9.2 NB_USER=iseki LC_ALL=en_US.UTF-8 PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin JUPYTERHUB_USER=iseki JUPYTERHUB_ACTIVITY_URL=http://172.22.1.75:8081/hub/api/users/iseki/activity DEBIAN_FRONTEND=noninteractive _=/usr/bin/env
新しいクラスを作成する
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/dockerspawner/
- edit __init__.py
- ex.) nsldockerspawner.py
...... from dockerspawner import DockerSpawner class NSLDockerSpawner(DockerSpawner): ...... def some_func(self): ret = super(NSLDockerSpawner, self).some_func() ..... return ret ...... def start(self, *, image=None, extra_create_kwargs=None, extra_host_config=None): ....... return super(NSLDockerSpawner, self).start()
MDLDockerSpawner
476 # refer: https://gist.github.com/marufeuille/596cf6f9e26fa6fcb7e304d5b163c7c8 477 from dockerspawner import SystemUserSpawner 478 from traitlets import Unicode 479 import pwd, os, grp 480 481 class ProjectDockerSpawner(SystemUserSpawner): 482 483 dobleArguments = False 484 #dobleArguments = True 485 486 487 host_homedir_format_string = Unicode( 488 "/home/{groupname}/{username}", 489 config = True, 490 ) 491 492 image_homedir_format_string = Unicode( 493 "/home/{groupname}/{username}", 494 config = True, 495 ) 496 497 498 @property 499 def host_homedir(self): 500 if ( 501 self.host_homedir_format_string is not None 502 and self.host_homedir_format_string != "" 503 ): 504 homedir = self.host_homedir_format_string.format(username=self.user.name, groupname=self.get_groupname()) 505 else: 506 import pwd 507 508 homedir = pwd.getpwnam(self.user.name).pw_dir 509 return homedir 510 511 512 @property 513 def homedir(self): 514 return self.image_homedir_format_string.format(username=self.user.name, groupname=self.get_groupname()) 515 516 517 def get_args(self): 518 args = super(ProjectDockerSpawner, self).get_args() 519 if (not self._user_set_cmd) and self.dobleArguments: 520 args = [] 521 return args 522 523 524 #def get_command(self): 525 # cmd = super(ProjectDockerSpawner, self).get_command() 526 # return cmd 527 # 528 # ''' 529 # if self._user_set_cmd: 530 # cmd = self.cmd 531 # else: 532 # image_info = yield self.docker("inspect_image", self.image) 533 # cmd = image_info["Config"]["Cmd"] 534 # return cmd + self.get_args() 535 # ''' 536 537 538 def template_namespace(self): 539 d = super(ProjectDockerSpawner, self).template_namespace() 540 if self.group_id >= 0: 541 d['groupname'] = self.get_groupname() 542 return d 543 544 545 def get_groupname(self): 546 gname = '' 547 if self.group_id >= 0: 548 gname = grp.getgrgid(self.group_id).gr_name 549 return gname 550 551 552 def get_env(self): 553 env = super(ProjectDockerSpawner, self).get_env() 554 if self.group_id >= 0: 555 #env.update(NB_GID=self.group_id) 556 import grp 557 gname = self.get_groupname() 558 env.update(NB_GROUP=gname) 559 return env 560 561 562 def start(self): 563 name = self.user.name 564 user_data = pwd.getpwnam(name) 565 user_gid = user_data.pw_gid 566 gid_list = os.getgrouplist(name, user_gid) 567 568 work_dir = self.notebook_dir 569 self.volumes['jupyterhub-user-{username}'] = work_dir 570 571 for gid in gid_list: 572 gname = grp.getgrgid(gid).gr_name 573 if gname.startswith("project-"): 574 dirname = gname.replace("project-", "") 575 self.volumes[gname] = work_dir + '/projects/' + dirname 576 577 return super(ProjectDockerSpawner, self).start()
jupyterhub-idle-culler
- jupyterhub_idle_culler
- https://github.com/jupyterhub/jupyterhub-idle-culler
- pip で入れると No module named が出て,動かない模様
- No module named jupyterhub_idle_culler
- GitHub から直接入れる.
- git clone https://github.com/jupyterhub/jupyterhub-idle-culler.git
- cd jupyterhub-idle-culler
- python setup.py build
- python setup.py build
- 期待通りに動かん!
- jupyterhub_config.py
lmport sys c.JupyterHub.services = [ { 'name': 'idle-culler', 'admin': True, 'command': [ sys.executable, '-m', 'jupyterhub_idle_culler', '--timeout=3600' ], } ]
cull_idle_servers.py
- jupyterhub-idle-culler は期待通りに動かない.cull_idle_servers.py の方が良いみたい.
- https://github.com/jupyterhub/jupyterhub/tree/a6b7e303df03865d6420f6bccdf627b39f1d0dc1/examples/cull-idle
- 実行状態(run)も確実に殺してくれる(stop でなくて, rm).
- Webで開いたままだとダメ
- jupyterhub_config.py
import sys c.JupyterHub.services = [ { 'name': 'idle-culler', 'admin': True, 'command': [ sys.executable, '/usr/local/bin/cull_idle_servers.py', '--timeout=3600' ], } ]
新しいファイルがパーミッションが無いとして,作成できない.
SystemUserSpawnar の場合は,まず現実のファイルのパーミッションをチェック- コンテナ内 に入って,ファイルのパーミッションをチェック. (力ずく!)
- start.sh の設定がダメダメだった.
- start.sh 内でパーミッションを設定すれば OK
DockerSpawner が self.get_env() で取れる情報
{ 'JUPYTERHUB_API_TOKEN': 'cfd4fbcd6ea6491492016765dbbf4805', 'JPY_API_TOKEN': 'cfd4fbcd6ea6491492016765dbbf4805', 'JUPYTERHUB_CLIENT_ID': 'jupyterhub-user-bob', 'JUPYTERHUB_HOST': '', 'JUPYTERHUB_OAUTH_CALLBACK_URL': '/user/bob/oauth_callback', 'JUPYTERHUB_USER': 'bob', 'JUPYTERHUB_SERVER_NAME': '', 'JUPYTERHUB_API_URL': 'http://172.22.1.75:8081/hub/api', 'JUPYTERHUB_ACTIVITY_URL': 'http://172.22.1.75:8081/hub/api/users/bob/activity', 'JUPYTERHUB_BASE_URL': '/', 'JUPYTERHUB_SERVICE_PREFIX': '/user/bob/', 'GRANT_SUDO': 'yes', 'USER': 'bob', 'NB_USER': 'bob', 'USER_ID': 1001, 'NB_UID': 1001, 'HOME': '/home/users/bob', 'NB_GID': 100 }
認証モジュール
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/ldapauthenticator/
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/ltiauthenticator/
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/jupyterhub/auth.py
Users
- 以下でやろうとしたこと(ユーザを jovyan以外する)は dockerspawner.SystemUserSpawner を使用すれば解決するので,没.
プロセスの起動順
- /opt/conda/bin/tini
- /usr/local/bin/start-notebook.sh
- /usr/local/bin/start-singleuser.sh
- /usr/local/bin/start.sh
最終的に起動されるプロセス
- /usr/local/bin/start.sh jupyterhub-singleuser "$@"
- /usr/local/bin/start.sh jupyter lab "$@"
- /usr/local/bin/start.sh jupyter notebook "$@"
デフォルトの引数例 $@
- --ip=0.0.0.0 --port=8888 --notebook-dir=/home/iseki/work --NotebookApp.default_url=/lab
起動コマンド
tini -g -- \ start-notebook.sh --ip=0.0.0.0 --port=8888 --notebook-dir=/home/teacher/iseki/jupyter --SingleUserNotebookApp.default_url=/lab
sudo -E -H -u iseki PATH=/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin XDG_CACHE_HOME=/home/teacher/iseki/.cache PYTHONPATH= \ jupyterhub-singleuser --ip=0.0.0.0 --port=8888 --notebook-dir=/home/teacher/iseki/jupyter --SingleUserNotebookApp.default_url=/lab
Docker の起動
- Docker の起動コマンド
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/dockerspawner/dockerspawner.py
- L804 の get_command()
下記機能の実現は環境変数によっても可能
- file
/usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/jupyterhub/spawner.py
- Docker に渡す引数の制御
- 任意のパラメータ(引数)に {username} 等を使用可能にする
c.DockerSpawner.args = ['--username={username}']
- self.format_string() を通すと {...} を処理してくれる.
- 任意のパラメータ(引数)に {username} 等を使用可能にする
- 注:SystemUserSpawner が正しく動けば, コンテナ内の環境変数 NB_USER で取れるので,以下のコード修正は不要.
- さらに jupyterhub_config.py 内などで新しい Class を定義してやれば,グループ名も取れる!
- さらに jupyterhub_config.py 内などで新しい Class を定義してやれば,グループ名も取れる!
code
- /usr/local/anaconda/envs/jupyterhub/lib/python3.8/site-packages/jupyterhub/spawner.py
- 継承を使う方がスマート
- 1.0.0
936 if self.debug: 937 args.append('--debug') 938 939 if self.disable_user_config: 940 args.append('--disable-user-config') 941 # Fumi 942 #args.extend(self.args) 943 for arg in self.args: 944 args.append(self.format_string(arg)) 945 return args
- 1.4.1
--- envs/jupyterhub/lib/python3.8/site-packages/jupyterhub/spawner.py.orig 2021-07-04 23:06:38.269817910 +0900 +++ envs/jupyterhub/lib/python3.8/site-packages/jupyterhub/spawner.py 2021-07-04 23:07:45.485894520 +0900 @@ -1024,7 +1024,10 @@ args.append('--debug') if self.disable_user_config: args.append('--disable-user-config') - args.extend(self.args) + ## Fumi Hax + #args.extend(self.args) + for arg in self.args: + args.append(self.format_string(arg)) return args def run_pre_spawn_hook(self):
Counter: 1886,
today: 2,
yesterday: 0
最終更新: 2021-10-16 (土) 14:22:59 (JST) (1059d) by iseki