带有 SystemUserSpawner 的 JupyterHub 失败

JupyterHub with SystemUserSpawner fails

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

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

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

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

在 运行ning (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

一切正常,但有一个不需要的警告:我现在是容器中的 root 用户,我在主目录中创建的任何文件都不属于 testuser,而是属于 (Docker容器)root。例如,在 VM 本身内部,testuser 无法删除这些文件。

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

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

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

我没有看到我遗漏了什么,也没有看到在哪里可以找到更多调试选项。因此欢迎任何建议。

Ubuntu18.04.2

上的 Jupyter(Hub) 版本 0.9.4

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

这将使用参数 jupyter labhub 启动 Docker 容器,类似于 运行 从命令行将其设置为 docker run jupyter/singleuser:0.9 jupyter labhub(带有一些额外的环境变量)。

但是,

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

# 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.shstart.sh 脚本,这些脚本实际上负责处理容器内的用户 ID 设置。也就是说,这些启动脚本会阻止 root 实际上 运行 执行 jupyter 命令。跳过脚本不会阻止这种情况,并且 jupyter 命令是 运行 root,问题中指出了问题。

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

  1. c.Spawner.cmd设置中包含start-notebook.shstart.sh(我直接选择了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(由 SystemUserSpawner 传递给 Docker 容器),并将 运行设置此变量时的实验室(因此,不一定需要将其设置为 '1')。在这种情况下,不需要将额外的参数传递给 Docker 容器或 start.sh 脚本,因此 c.Spawner.cmd 被禁用。