Skip to content

Instantly share code, notes, and snippets.

@tanbro
Last active April 28, 2024 13:58
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save tanbro/a94bfa4a552381f599e7e6b551ccadcf to your computer and use it in GitHub Desktop.
Save tanbro/a94bfa4a552381f599e7e6b551ccadcf to your computer and use it in GitHub Desktop.
单机多用户 JupyterLab 环境搭建

单机多用户 JupyterLab 环境搭建

概述

在这篇短文中,我们记录了如何在使用 Ubuntu 1804 LTS 操作系统的单台服务器上,建立用户隔离的 JupyterLab Web 环境。

目标是:

  • 操作系统的用户可以各自不受干扰的使用独立的 JupyterLab
  • 各个用户的 Conda 环境可以自动的出现在 JupyterLabKernel 列表中
  • 每个用户都可以新建自己的 Conda 或者 venv 环境,并在其中安装 Condapip 软件
  • 可以在 notebook 中使用本机的 NVIDIA GPU

准备工作

  1. 为服务器安装 Ubuntu 1804 长期支持版。 如果需要使用 NVIDIA GPU,建议安装带有完整图形界面的桌面版操作系统,以简化配置。

  2. 确保服务器可以连接到互联网

  3. 更新服务器上的软件包,在终端执行:

    sudo apt update
    sudo apt upgrade --auto-remove
  4. 如果需要使用 NVIDIA GPU,应安装其驱动。

    说明:

    • 由于我们准备在 Conda 环境中安装配置 Jupyter Kernel ,故仅安装 Driver,而不在操作系统级别安装 CUDAcuDNN 等软件包。 推荐的方式是:各用户自行在各个环境中使用 Conda 分别安装这些软件包。
    • NVIDIA 官方网站提供的 Driver 安装过程比较繁琐,涉及到 Linuxmodprobeinitramfs 的修改,本文不予记载。
    • 所采用的 NVIDIA Driver 版本应根据操作系统版本、 Graphic 设备和 CUDA 版本要求决定。具体应参考 NVIDIA 网站说明。

    本文中,我们使用 Apt 安装 NVIDIA Driver 最新的长期支持版(以430为例):

    提示:

    我们可通过 https://www.nvidia.com/object/unix.html 获知 Unix 驱动的版本支持信息

    • 字符界面安装

      sudo add-apt-repository restricted
      sudo apt-get update
      sudo apt-get install nvidia-driver-430
    • 图形界面安装

      1. 打开 “软件和更新” 系统应用
      2. 在该应用的 “Ubuntu 软件” 选项卡中,选中 "设备的专有驱动(restricted)" 选项
      3. 在该应用的 “附加驱动” 选项卡中,待 “搜索可用驱动” 完毕后,选择 NVIDIA Corporation 下最新的长期支持版驱动版本

安装和配置 JupyterHub

安装 JupyterHub

我们将在操作系统级安装 JupyterHub,并以 root 身份运行该软件,以便启停其它账户的 JupyterLab 进程。

JupyterHub 在启动时执行 configurable-http-proxy 进程,用它来反向代理目标用户 JupyterLabHTTP 通信。不过,它无法配置 configurable-http-proxy 的路径。

所以,我们还需要在操作系统级安装 configurable-http-proxy

  1. 安装 JupyterHub

    这是一个 Python 程序,且没有官方 Apt 源。所以,我们用 pip 安装。

    1. apt 安装 Pythonpip:

      sudo apt install python3 python3-pip
    2. 使用 pip 安装 JupyterHub,注意要在操作系统级安装:

      sudo -H pip3 install -U jupyterhub
  2. 安装 configurable-http-proxy

    这是一个 Node.js 程序,且没有官方 Apt 源。所以,我们用 npm 安装。

    1. apt 安装 Node.jsnpm:

      sudo apt install nodejs npm
    2. npm 安装 configurable-http-proxy,注意要在操作系统级安装:

      sudo npm install -g configurable-http-proxy

配置 JupyterHub

我们采用 JupyterHub 默认的 single-user 模式,其登录用户就是操作系统的账户。

但是,为了实现我们的需求,还需修改配置文件,让 JupyterHub 登录进入用户的 shell 之后,以目标用户的身份执行 jupyterhub-singleuser 进程,而不是直接在当前进程的环境中直接启动。

  1. 生成默认配置文件

    生成默认配置文件 jupyterhub_config.py,将它移动到系统目录,如 /etc/jupyterhub,并重命名为 config.py:

    jupyterhub --generate-config
    sudo mkdir -p /etc/jupyterhub
    sudo cp jupyterhub_config.py /etc/jupyterhub/config.py
  2. 修改配置文件

    1. 修改 single-user-spawner 的默认启动方式(必须

      这是最为重要的一个步骤! 我们通过该设置,让 JupyterHub 以目标用户的身份登录 bash,然后运行 jupyterhub-singleuser,由这个进程此启动用户环境中的 JupyterLab

      c.LocalProcessSpawner.shell_cmd = ["bash", "-l", "-c"]
    2. 使用 JupyterLab 而非 Jupyter notebook可选

      c.Spawner.default_url = "/lab"
    3. 设置 JupyterHub Web 服务的 HTTP 地址(可选)。应根据实际网络规划设置,如:

      c.JupyterHub.ip = "0.0.0.0"
    4. 不用确保运行 JupyterLab 的环境处于 Kenerl 在列表中(可选

      c.Spawner.args = ["--KernelSpecManager.ensure_native_kernel=False"]

后台运行 JupyterHub

编辑以下文本到 systemd 配置文件 jupyterhub.service

[Unit]
Description=Jupyterhub service
After=syslog.target network.target

[Service]
ExecStart=/usr/local/bin/jupyterhub -f /etc/jupyterhub/config.py

[Install]
WantedBy=multi-user.target

然后将它复制到 systemd 系统配置目录,并修改权限:

sudo cp jupyterhub.service /etc/systemd/system
sudo chmod 644 /etc/systemd/system/jupyterhub.service

最后,刷新服务列表并启动该服务:

sudo systemctl daemon-reload
sudo systemctl start jupyterhub

如果需要该服务自动运行,执行:

sudo systemctl enable jupyterhub

进程调用关系示意图

digraph G {
   graph [
      label="进程调用关系示意图"
   ];
   browser [shape=box, color=blue];
   hub [label="root:/usr/loca/bin/jupyterhub", color=red];
   proxy [label="root:/usr/local/bin/configurable-http-proxy", color=red];
   bash [label="root: sudo -u USER -i bash -l -c 'jupyterhub-singleuser'", color="lightblue"];
   user [label="USER:jupyterhub-singleuser", color=yellowgreen];
   lab [label="USER:jupyter-lab", color=green];
   kernel  [label="USER:<path/of/installed/kernel/>python", color=green];
   browser -> proxy -> lab [label=http, color=blue];
   browser -> kernel [style=dashed, color=gray];
   hub -> proxy [label=subprocess];
   hub -> bash -> user -> lab -> kernel [label=subprocess];
}

![进程调用关系示意图](https://g.gravizo.com/svg?digraph G { graph [ label="进程调用关系示意图" ]; browser [shape=box, color=blue]; hub [label="root:/usr/loca/bin/jupyterhub", color=red]; proxy [label="root:/usr/local/bin/configurable-http-proxy", color=red]; bash [label="root: sudo -u USER -i bash -l -c 'jupyterhub-singleuser'", color="lightblue"]; user [label="USER:jupyterhub-singleuser", color=yellowgreen]; lab [label="USER:jupyter-lab", color=green]; kernel [label="USER:<path/of/installed/kernel/>python", color=green]; browser -> proxy -> lab [label=http, color=blue]; browser -> kernel [style=dashed, color=gray]; hub -> proxy [label=subprocess]; hub -> bash -> user -> lab -> kernel [label=subprocess]; })

用户环境

每个操作系统的普通用户,都可以使用 JupyterHub 的 Web 界面,通过操作系统用户名和密码登录到用户隔离的 JupyterLab 进程。

但是,在此之前,我们还需要为这些用户安装软件、修改配置。

本章节中记录的后续操作,均假定已使用目标用户身份登录。

安装 Conda

首先,为这个用户安装 Conda。为了安装配置过程的轻便,我们在本例中采用 Miniconda 而非 Anaconda

执行:

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh

然后按照提示,使用默认值进行安装。

当安装程序输出下面的提示时:

installation finished.
Do you wish the installer to initialize Miniconda3
by running conda init? [yes|no]
[no] >>>

输入 yes

安装完成后,执行以下命令或者重新登录:

source ~/.bashrc

在 Conda base 环境中安装必备软件

Conda base 环境中安装 Jupyter, JupyterLab, JupyterHub, nb_conda 等相关软件包,推荐使用 conda-forge 通道:

conda install -n base  -c conda-forge jupyter jupyterlab jupyterhub nb_conda widgetsnbextension

完成后,安装 JupyterLab 的 Web 扩展 jupyterlab-manager (可选):

jupyter labextension install @jupyter-widgets/jupyterlab-manager

修改 ~/.profile 配置文件

我们还需要将 Conda base 环境的 bin 目录加到 PATH 环境变量。 这是因为,我们修改了 JupyterHub 的配置,并让不同用户使用各种环境中不同路径的 jupyterhub-singleuser;而 JupyterHubSingleUserSpawner 在登录目标用户 bash 并执行 jupyterhub-singleuser 时,以及 jupyterhub-singleuser 执行 JupyterLab 时, 均无法指定路径。 为此,我们将在该用户的 Conda base 环境下安装 JupyterHubJupyterLab ,且需确保 JupyterHubSingleUserSpawner 在登录该用户的 bash 时将上述 base 环境的执行目录自动加入到 PATH 环境变量。 这样,SingleUserSpawnerjupyterhub-singleuser 就可以搜索到执行文件了。

我们可以修改 ~/.profile 配置,使得 JupyterHub 登录到该用户的 bash 时,PATH 被修改。

方法是:

  • ~/.profile 的末尾加上:

    PATH="/home/USER/miniconda3/bin:$PATH"

    其中 USER 表示用户名;如果使用的是 anaconda,目录会有所不同。应根据实际情况设置。

  • 也可用以下 shell 脚本在 ~/.profile 的最后一行添加上述内容:

    echo "PATH=\"$(dirname $CONDA_EXE):\$PATH\"" | tee -a ~/.profile

新建 Jupyter Kernel

Conda 环境自动添加到 Kernels 列表

如果在用户的 Conda 环境安装 ipythonnb_condanb_conda 会自动在Jupyter(其所在环境也需要安装 nb_conda) 的 Kernels 列表中添加其所在的环境。

例如,新建一个名为 myenv 的环境,在这个环境安装 ipythonnb_conda,刷新页面,就可以在Kenerls列表中看到这个环境了。

新建这样一个环境,命令是:

conda create -n myenv ipython nb_conda ipywidgets

对于已经存在的 Conda 环境,可以随时安装 ipythonnb_conda。一旦安装,即可被 JupyterLab(中的 nb_conda)检测到。

手动添加 Python 环境到 Kernels 列表

任何 Python 环境,无论是系统级、用户级、venv 还是 Conda 环境,凡是安装了 ipython 软件包的,都可以手动添加到 JupyterKernels 列表。

方法是在激活的目标环境中执行:

python -m ipykernel install --user --name="myenv" --display-name="My environment"

具体参考: https://ipython.readthedocs.io/en/stable/install/kernel_install.html

安装软件包

⚠ 警告:

为了防止 base 环境被意外破坏,我们不应在 base 环境中进行工作或者安装/删除/修改软件包。

推荐的方式是:为每项工作单独维护一个 Conda 环境

使用 Conda 安装

常规的方法是通过终端使用 conda 命令指定或者激活目标环境后进行安装。

也可以在 Jupyter 笔记本中,使用“魔术方法”安装,如: %conda install tqdm

ℹ 注意:

%conda 所使用的 Conda 环境 与笔记正在使用的 Kernel 的是一致的。

为保险起见,可执行 %conda env list 查看。

使用 pip 安装

常规的方法是通过终端切激活目标环境,然后使用 pip 命令进行安装。

也可以在 Jupyter 笔记本中,使用“魔术方法”安装,如: %pip install tqdm

ℹ 注意:

%pip 所使用的环境与笔记正在使用的 Kernel 的是一致的。

为保险起见,可执行 %pip --version 查看。

实例

新建用户环境

在这个实例中,我们新建一个操作系统用户,使用 JupyterHub Web GUI,以该用户身份登录;并且在这个用户名下新建一个 Conda 环境,让 JupyterLab 自动将该环境加入到其 Kernels 列表。

  1. 新建用户

    假定用户名为 {{USER}}:

    sudo adduser {{USER}}
  2. 为新建的用户安装 Conda

    以上一步骤中新建的 {{USER}} 身份登录。为了提高网速,建议使用清华大学 Anaconda 镜像

    1. 下载 Miniconda:

      wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh
    2. 安装 Miniconda(参考 安装 Conda 一节):

      bash Miniconda3-latest-Linux-x86_64.sh
    3. 更新 bash 环境:

      source .bashrc
  3. 修改环境变量 PATHConda 配置

    1. 修改用户配置文件中的搜索路径环境变量:

      echo "PATH=\"$(dirname $CONDA_EXE):\$PATH\"" >> ~/.profile
    2. 修改 Conda 的用户配置文件 ~/.condarc,设置清华大学 Anaconda 镜像:

      channels:
        - defaults
      show_channel_urls: true
      default_channels:
        - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
        - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
      custom_channels:
        conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
        pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
  4. base 环境安装 jupyter, jupyterlab, jupyterhub, nb_conda 等软件包(推荐使用 conda-forge 通道):

    conda install -n base jupyter jupyterlab jupyterhub nb_conda widgetsnbextension -c conda-forge
  5. 安装 JupyterLab 的 几个常用 Web 扩展(可选):

    jupyter-labextension install @jupyter-widgets/jupyterlab-manager @jupyterlab/toc

新建 Conda 环境,安装软件包

建议在 base 环境中直接进行工作,以避免破坏运行 JupyterHubJupyterLab 的基础环境。

所以,我们一般会为每一项工作单独新建一个 Conda 环境。

  1. 新建 Conda 环境

    新建的环境如果具有软件包 ipythonnb_conda,就可以被 Jupyter (其所在环境也需要安装 nb_conda)自动检测到。

    此处,我们新建一个名为 mypy36、使用 Python 3.6 的环境为例:

    conda create --name mypy36 python=3.6 ipython nb_conda ipywidgets

    等一小会儿,查看页面,这个环境是不是已经出现在 Kernels 列表中了?

  2. 安装软件包。

    下面,我们在这个环境中安装一个软件包。例如,我们想要安装 pandas

    JupyterLabNotebook 的代码 cell 中,或者 Console 的命令输入框中,使用魔法命令 %conda 或者 %pip 安装。该软件包会安装到该 Notebook 或者 Console 所使用的 Kernel 对应环境中。

    • Conda 安装(在笔记的 Cell 中执行)

      %conda install pandas
    • pip 安装(在笔记的 Cell 中执行)

      %pip install pandas

    此外,也可以通过终端,直接使用 conda 或者 pip 命令行安装。安装时注意不要搞错环境

    ❗ 重要:

    对于类似于 tensorflow-gpu 这样依赖复杂的大型第三方 C/C++ libraries(它依赖 CUDA, cuDNN)、构建复杂、且其 wheel 包无法提供完整预编译库/可执行文件的软件包,建议使用 Conda 进行安装。这样可以简便的解决库依赖和环境隔离问题,避免从源代码编译。

ℹ 提示:

如果 pip 以及 conda 官方源镜像的网络条件不好,可以考虑使用国内的镜像。


@GTSeventeEn
Copy link

作者您好,感谢您的教程。有一个问题,A用户是无法使用B用户创建的conda环境吗?因为测试没有成功,想要问一下、

@tanbro
Copy link
Author

tanbro commented Oct 12, 2019

作者您好,感谢您的教程。有一个问题,A用户是无法使用B用户创建的conda环境吗?因为测试没有成功,想要问一下、

@GTSeventeEn 感谢关注!

是的,A用户无法为B用户创建 Conda 环境!
我认为,按照这篇短文记录的方法,用户之间无法共享 Conda 环境 —— 因为不同操作系统账户之间的 conda 路径不同、且隔离。

Copy link

ghost commented Feb 12, 2020

我这几天也在折腾这个环境,考虑到仅靠 Jupyter 来隔离用户好像有点不太放心,最后选择了用 Docker 的方式,每个用户都是 root,在自己的环境里随便搞哈哈哈哈哈

@tanbro
Copy link
Author

tanbro commented Mar 9, 2020

我这几天也在折腾这个环境,考虑到仅靠 Jupyter 来隔离用户好像有点不太放心,最后选择了用 Docker 的方式,每个用户都是 root,在自己的环境里随便搞哈哈哈哈哈

是的,Docker 作隔离显然更好

@A2Data
Copy link

A2Data commented Aug 17, 2021

作者您好。 我跟您的教程安装。 理论上不是只需要搭建一套环境 即可么 为什么还要分用户来重新安装呢?

@A2Data
Copy link

A2Data commented Aug 17, 2021

我使用的 是 unbuntu 18.04 ,安装途中有很多问题的。 比如 node 需要10版本以上。 步骤是不是太多了 对我进行了干扰。。。

@tanbro
Copy link
Author

tanbro commented Aug 20, 2021

@A2Data 你好!我有一段时间没有用 JupyterHub 了,不知道现在的版本是什么情况。

当时,我做这样的环境,是为了在一台具有多个nv卡的物理服务器上,和成员共享硬件环境,和 jupyter 软件。

由于不同成员做不同的事,需要不同的软件包环境,所以选择让 jupyterhub 使用操作系统用户登录,成员自行维护自己的多个 conda 或者 pip 或者其它jupyter支持的运行时环境。

如果现在的 Jupyter 需要操过 ubuntu1804 apt 源的 nodejs 版本,我想,也许可以自行安装,或者使用更高版本的 ubuntu。

另外,个人觉得,使用 docker 也许是更简单的多环境隔离方法。

@A2Data
Copy link

A2Data commented Aug 20, 2021 via email

@tanbro
Copy link
Author

tanbro commented Aug 21, 2021

按照这个 gist ,如果我没有记错的话,当时,我选择了 single-user-spawner 模式,以 root 运行 JupyterHub

当新建用户之后,要给每个新建的用户安装 Jupyterlab (我当时好像是在 conda 的 base 装的),且这个用户的 ~/.profile 设置 $PATH 包含 CONDA 的路径(为了启动 jupyterlab)。

这样,貌似当通过 JupyterHub 登录时, Jupyterhub 就会以 web 上输入的用户密码去 spawn 一个 shell,在这个环境上运行 conda 的 jupyterlab

@tanbro
Copy link
Author

tanbro commented Aug 21, 2021

我记得,当时这样干,主要是为了每个 user 直接用自己的 $HOME 放数据文件模型什么的(我想,如果用 docker,设置好 volumn 也一样);在一个就是每个人自己在干不同的活儿的时候,设不同的 conda 或者 pip 环境,不互相影响(我想,如果用 docker ,每个环境起一个 container 也一样)

@A2Data
Copy link

A2Data commented Aug 22, 2021 via email

@tanbro
Copy link
Author

tanbro commented Aug 24, 2021

@A2Data ;) 不客气,希望能够有所帮助.

@scruel
Copy link

scruel commented Nov 9, 2022

有办法用 ssh key 的方式登录吗?不想把 jupyterhub 装在 root 下怎么做到同样的效果呢?

@tanbro
Copy link
Author

tanbro commented Nov 11, 2022

jupyterlab 的 Web UI 应该不能用 SSH Key 登录吧。
据我所知 jupyterhub 如果要多用户登录,应该需要 root 权限 (https://jupyterhub.readthedocs.io/en/latest/quickstart.html#start-the-hub-server)。
猜测如果不是 PAM 登录而是 OAuth 登录,也许不用 root。

@ZWBSJSW
Copy link

ZWBSJSW commented Apr 27, 2024

非常感谢作者的详尽解答,我在同一ubuntu操作系统(操作系统本身已经安装了anaconda)创建了多个jupyterhub用户,我发现新建用户是无法使用conda的,那么可以使用您提供的方法嘛,会不会把已有系统装好的anaconda覆盖呢?非常期待作者大神的解答!

@tanbro
Copy link
Author

tanbro commented Apr 28, 2024

非常感谢作者的详尽解答,我在同一ubuntu操作系统(操作系统本身已经安装了anaconda)创建了多个jupyterhub用户,我发现新建用户是无法使用conda的,那么可以使用您提供的方法嘛,会不会把已有系统装好的anaconda覆盖呢?非常期待作者大神的解答!

如果没有记错的话,这需要在新建用户后,为新用户安装/配置好 conda/miniconda 。 JupyterLab 起来后,以这个新用户身份登录到操作系统,参考 gist 的 section:https://gist.github.com/tanbro/a94bfa4a552381f599e7e6b551ccadcf#%E6%96%B0%E5%BB%BA%E7%94%A8%E6%88%B7%E7%8E%AF%E5%A2%83

也就是说, JupyterLab 在一个专门的(或者 root)的OS账户上的 conda 或者 venv 环境中运行,然后每个操作系统用户,都得安装自己的 conda 环境,建议为每一项工作建立一个独立的 conda,避免软件包冲突。

单机上原生用户的配置还是比较繁琐的,这个 gist 很久没有更新了,建议考虑使用容器来达成相似的目的,应该更为简易。

谢谢,祝好

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment