jupyterhub - 带有 SystemUserSpawner 的 JupyterHub 失败
问题描述
我正在尝试使用生成的dockerspawner.SystemUserSpawner
Jupyter Lab 实例在虚拟机上运行 JupyterHub。
我的 jupyterhub_config.py 有以下(额外的)行:
c.Spawner.default_url = '/lab'
c.Spawner.cmd = ['jupyter', 'labhub']
c.JupyterHub.spawner_class = 'dockerspawner.SystemUserSpawner'
(加上bind_url
and的行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
解决方案
错误在c.Spawner.cmd
( c.Spawner.cmd = ['jupyter', 'labhub']
) 中。
这将使用 arguments 启动 Docker 容器jupyter labhub
,类似于从命令行运行它docker run jupyter/singleuser:0.9 jupyter labhub
(使用一些额外的环境变量)。
但是,Docker 会将容器名称之后的第一个参数读取为CMD
,而不是CMD
Dockerfile 中的参数。也就是说,基本笔记本(以及 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 身份运行,问题中指出了问题。
有两种可能的方法。我不清楚哪一个是首选:
包括
start-notebook.sh
或start.sh
在c.Spawner.cmd
设置中(我直接选择了start.sh
):c.Spawner.cmd = ['start.sh', 'jupyter', 'labhub']
这会将
start-notebook.sh
命令替换为start.sh
(这通常很好;第一个是第二个的小包装),jupyter labhub
然后将作为参数提供给start.sh
. 这正是需要的。设置环境变量,
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
through 传递给 Docker 容器),并在设置此变量时运行实验室(因此,不一定需要设置'1'
)。在这种情况下,不需要将额外的参数传递给 Docker 容器或start.sh
脚本,因此c.Spawner.cmd
被禁用。
推荐阅读
- sql - PostgreSQL:如何从数据输出中编辑数据?
- python - 如何在 IMDB 页面上找到总价值
- c# - 尽管代码有效,但 Visual Studio 2017 Designer 'Invalid Markup' 错误
- c# - 什么会导致 DbSet 中的持久实体被分离?
- google-apps-script - Google App Script - 如何从库中调用函数
- reactjs - 在不同的基于虚拟 DOM 的 UI 库(React、Inferno、Preact 等)中处理“ref”和“key”
- typescript - Phaser + TypeScript 严格模式
- c# - 在集中提交到 aspx 页面之前修剪所有控件的空间
- android - 如何使用场景形式从场景中删除选定的对象?
- java - Hibernate JPA @Generated 注解编译错误