首页 > 解决方案 > 带有 SystemUserSpawner 的 JupyterHub 失败

问题描述

我正在尝试使用生成的dockerspawner.SystemUserSpawnerJupyter Lab 实例在虚拟机上运行 JupyterHub。

我的 jupyterhub_config.py 有以下(额外的)行:

c.Spawner.default_url = '/lab'
c.Spawner.cmd = ['jupyter', 'labhub']
c.JupyterHub.spawner_class = 'dockerspawner.SystemUserSpawner'

(加上bind_urland的行hub_ip)。其他一切都应该是默认的。

运行 ( jupyterhub -f /etc/jupyterhub/jupyterhub_config.py) 并在浏览器中登录后,我遇到了 500 错误。命令行上的日志如下所示:

[D 2019-02-26 16:55:37.869 JupyterHub dockerspawner:644] Getting container 'jupyter-testuser'
[D 2019-02-26 16:55:37.873 JupyterHub dockerspawner:629] Container 8bf627d status: {'Dead': False,
     'Error': '',
     'ExitCode': 1,
     'FinishedAt': '2019-02-26T15:55:29.518823812Z',
     'OOMKilled': False,
     'Paused': False,
     'Pid': 0,
     'Restarting': False,
     'Running': False,
     'StartedAt': '2019-02-26T15:55:28.446881243Z',
     'Status': 'exited'}
[W 2019-02-26 16:55:37.874 JupyterHub web:1667] 500 GET /hub/user/testuser/ (www.xxx.yyy.zzz): Spawner failed to start [status=ExitCode=1, Error='', FinishedAt=2019-02-26T15:55:29.518823812Z]. The logs for testuser may contain details.
[D 2019-02-26 16:55:37.875 JupyterHub base:880] No template for 500

然后,JupyterHub 本身陷入(无休止?)循环,试图每 10 秒生成一次容器。

忽略丢失的 500 模板,我从容器状态消息中变得更加明智,但docker logs jupyter-testuser显示:

....
[C 2019-02-26 15:55:29.360 SingleUserLabApp notebookapp:1707] Running as root is not recommended. Use --allow-root to bypass.
[D 2019-02-26 15:55:29.360 SingleUserLabApp application:647] Exiting application: jupyter-notebook

当我更改jupyterhub_config.py为包含

c.Spawner.cmd = ['jupyter', 'labhub', '--allow-root']
c.DockerSpawner.remove = True

事情确实有效,但有一个不需要的警告:我现在是容器中的根,并且我在主目录中创建的任何文件都不属于testuser,而是属于 (Docker container) root。例如,在 VM 本身内部,testuser无法删除这些文件。

(注意c.DockerSpawner.remove = True:如果我不包括在内,JupyterHub 会卡在之前没有的容器上--allow-root

文档建议初始配置应该是正确的,并且--allow-root对于标准 docker 堆栈不是必需的(我显然在这里使用默认配置,jupyterhub/singleuser:0.9)。

为了比较,使用dockerspawner.DockerSpawner效果很好。

我看不到我缺少什么,或者在哪里寻找更多调试选项。因此,欢迎提出任何建议。

Ubuntu 18.04.2 上的 Jupyter(Hub) 版本 0.9.4

标签: jupyterhub

解决方案


错误在c.Spawner.cmd( c.Spawner.cmd = ['jupyter', 'labhub']) 中。

这将使用 arguments 启动 Docker 容器jupyter labhub,类似于从命令行运行它docker run jupyter/singleuser:0.9 jupyter labhub(使用一些额外的环境变量)。

但是,Docker 会将容器名称之后的第一个参数读取为CMD,而不是CMDDockerfile 中的参数。也就是说,基本笔记本(以及 jupyter/singleuser 笔记本)的 Dockerfile 具有以下内容:

# Configure container startup
ENTRYPOINT ["tini", "-g", "--"]
CMD ["start-notebook.sh"]

这将使用下一个命令运行入口点,即tini -g -- start-notebook.sh,后跟给定的参数docker run。但是,由于第一个参数替换了CMD,所以执行的是tini -g -- jupyter,并labhub作为参数传递给jupyter。后者绕过了脚本,start-notebook.sh因此start.sh脚本实际上负责处理容器内的用户 ID 设置。也就是说,这些启动脚本会阻止 root 实际运行 jupyter 命令。跳过脚本不会阻止这种情况,并且 jupyter 命令以 root 身份运行,问题中指出了问题。

有两种可能的方法。我不清楚哪一个是首选:

  1. 包括start-notebook.shstart.shc.Spawner.cmd设置中(我直接选择了start.sh):

    c.Spawner.cmd = ['start.sh', 'jupyter', 'labhub']
    

    这会将start-notebook.sh命令替换为start.sh(这通常很好;第一个是第二个的小包装),jupyter labhub然后将作为参数提供给start.sh. 这正是需要的。

  2. 设置环境变量,JUPYTER_LAB_ENABLE禁用c.Spawner.cmd

    #c.Spawner.cmd = ['start.sh', 'jupyter', 'labhub']
    c.SystemUserSpawner.environment = {'JUPYTER_ENABLE_LAB': '1'}
    

    查看start.sh环境变量JUPYTER_ENABLE_LAB(通过SystemUserSpawnerthrough 传递给 Docker 容器),并在设置此变量时运行实验室(因此,不一定需要设置'1')。在这种情况下,不需要将额外的参数传递给 Docker 容器或start.sh脚本,因此c.Spawner.cmd被禁用。


推荐阅读