我正在尝试使用dockerspawner.SystemUserSpawner
在虚拟机上运行JupyterHub,并生成Jupyter Lab实例。
我的jupyterhub_config.py具有以下(附加)行:
c.Spawner.default_url = '/lab'
c.Spawner.cmd = ['jupyter', 'labhub']
c.JupyterHub.spawner_class = 'dockerspawner.SystemUserSpawner'
(为bind_url
和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容器){{ 1}}。在虚拟机本身内部,root
无法删除这些文件。
(请注意testuser
:如果我不包括该内容,JupyterHub将卡在先前没有c.DockerSpawner.remove = True
的容器上)
文档建议初始配置应该正确,对于标准docker堆栈,--allow-root
并不是必需的(我显然在这里使用默认的--allow-root
)。
为进行比较,使用jupyterhub/singleuser:0.9
效果很好。
我看不到我所缺少的内容,或者在哪里可以找到更多的调试选项。因此,欢迎提出任何建议。
Ubuntu 18.04.2上的Jupyter(Hub)0.9.4版本
答案 0 :(得分:1)
错误出在c.Spawner.cmd
(c.Spawner.cmd = ['jupyter', 'labhub']
)。
这将以参数jupyter labhub
启动Docker容器,类似于从命令行以docker run jupyter/singleuser:0.9 jupyter labhub
的方式运行它(带有一些其他环境变量)。
但是,Docker将读取容器名称之后的第一个参数为CMD
,而不是Dockerfile中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
作为{的参数{1}}。正是需要的。
设置环境变量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
传递到Docker容器),并在设置此变量后运行实验室(因此,不一定需要将其设置为SystemUserSpawner
。在这种情况下,不需要将额外的参数传递给Docker容器或'1'
脚本,因此start.sh
被禁用。