草庐IT

Linux部署JupyterHub实现多用户使用Jupyterlab

xjfyt 2023-11-06 原文

一、安装docker

1、安装

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

2、配置

# 重启docker
systemctl restart docker 

# 设置docker为开机自启动
systemctl enable docker

二、拉取镜像并创建容器

1、拉取镜像

docker pull debian:latest

2、创建容器

docker run -itd --hostname=jupyterhub -v /etc/jupyterhub:/etc/jupyterhub --name=jupyterhub --restart=always -p 8000:8000 debian

此处使用debian作为基本镜像进行搭建,也可以使用ubuntucentos等镜像,对外暴露端口号为8000,若有端口冲突,可改为其他端口,jupyterlab服务运行在容器的8000端口上。

3、进入容器

创建完成后进入容器,接下来的众多命令均在容器内执行:

docker exec -it jupyterhub /bin/bash

三、安装必要的包

1、更新软件源

apt-get update -y && apt-get upgrade -y && apt-get autoremove -y

2、安装软件

apt-get install vim procps wget -y

四、安装Miniconda3

1、获取下载地址

下载地址:Miniconda3清华镜像站下载

选择较新版本,复制链接,

2、下载并安装

# 下载
wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-py39_4.12.0-Linux-x86_64.sh

# 赋予可执行权限
chmod +x ./Miniconda3-py39_4.12.0-Linux-x86_64.sh

# 执行安装
./Miniconda3-py39_4.12.0-Linux-x86_64.sh

执行安装后,有几点注意:

  • 刚执行的时候是服务条款,一路按Enter,然后要输入的时候输入yes即可;

  • 接下来会让确认路径,默认为~/miniconda3,不要装在root用户目录下,建议装在/opt/miniconda3目录下,装root目录下之后会出现很多问题;

  • 最后询问是否初始化,选择yes

  • 安装完成后可删除安装包,以节省硬盘空间

3、验证是否安装成功

安装完成后重启终端,然后再进去,再进入发现终端(base)开头,说明安装成功

五、安装nodejs和npm

nodejsnpm可以使用apt-get包管理工具进行安装:

apt install nodejs npm -y 

但版本可能不是很新,以下提供另一种安装方法:

1、下载

node.js中文官网:下载 | Node.js 中文网 (nodejs.cn)

访问界面,选择Linux 二进制文件 (x64),右键复制链接

返回终端,下载:

wget https://nodejs.org/dist/v16.17.0/node-v16.17.0-linux-x64.tar.xz

解压:

tar -xvf ./node-v16.17.0-linux-x64.tar.xz

移动并重命名

mv node-v16.17.0-linux-x64/ /opt/nodejs

2、配置环境变量

vim /etc/bash.bashrc

追加以下内容:

#set for nodejs
export NODE_HOME=/opt/nodejs
export PATH=$NODE_HOME/bin:$PATH

使环境变量立即生效

source /etc/bash.bashrc

3、验证

nodejsnpm安装完成,使用以下命令进行验证

node -v # 查看node.js版本
npm -v  # 查看npm版本

六、配置镜像源

npm、pip和conda的软件源都是国外的,在国内访问比较慢,换源有利于提高下载速度。

1、npm换源

npm config set registry http://registry.npmmirror.com  # npm换淘宝源

2、pip换源

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # pip换清华源

3、conda换源

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/  
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/    
conda config --set show_channel_urls yes 

七、时区设置

不设置时区后续可能会出现一些问题。

终端执行:

dpkg-reconfigure tzdata

选择时区时选择Asia/Shanghai

八、安装jupyter相关的库

1、需要npm安装的

npm install -g configurable-http-proxy

2、需要conda安装的

conda install pycurl 

pycurl必须用conda装,用pip装会报错,或用源码编译安装,没有pycurl就会导致普通用户无法开启jupyterlab

3、需要pip安装的

pip install jupyterlab jupyterhub jupyterhub-idle-culler autopep8 pycodestyle mccabe pycodestyle pydocstyle pyflakes pylint rope yapf whatthepatch

解释一下安装的包的含义:

  • jupyterlabjupyter notebook环境
  • jupyterhubjupyterhub主体程序
  • jupyterhub-idle-culler用于处理用户空闲进程

九、配置jupyterhub

1、生成配置文件

jupyterhub --generate-config -f /etc/jupyterhub/jupyterhub_config.py

2、编辑配置文件

vim /etc/jupyterhub/jupyterhub_config.py

将以下内容追加到配置文件/etc/jupyterhub/jupyterhub_config.py

import sys

c.Authenticator.admin_users = {'root'}  # 管理员用户
# 管理员是否有权在各自计算机上以其他用户身份登录,以进行调试,此选项通常用于 JupyterHub 的托管部署,以避免在启动服务之前手动创建所有用户
c.JupyterHub.admin_access = True
c.PAMAuthenticator.open_sessions = False # 解决多用户同时登录问题。
c.Spawner.args = ['--allow-root']  # 允许root用户使用
c.LocalAuthenticator.create_system_users = True  # 允许创建其他用户
c.Spawner.notebook_dir = '~'  # 设置工作目录
c.Spawner.default_url = '/lab'

c.JupyterHub.extra_log_file = '/etc/jupyterhub/jupyterhub.log' # 指定额外的日志
c.JupyterHub.pid_file='/etc/jupyterhub/jupyterhub.pid' # 指定pid文件位置
c.JupyterHub.db_url='/etc/jupyterhub/jupyterhub.sqlite' # 指定数据库文件位置
c.JupyterHub.cookie_secret_file='/etc/jupyterhub/jupyterhub_cookie_secret'  # 指定cookie_secret文件位置
c.ConfigurableHTTPProxy.pid_file='/etc/jupyterhub/jupyterhub-proxy.pid' # 设置proxy.pid文件位置


# 设置用户一小时内无使用则关闭jupyterlab服务
c.JupyterHub.services = [
    {
        'name': 'idle-culler',
        'command': [sys.executable, '-m', 'jupyterhub_idle_culler', '--timeout=1800'],
    }
]

c.JupyterHub.load_roles = [
    {
        "name": "list-and-cull",  # name the role
        "services": [
            "idle-culler",  # assign the service to this role
        ],
        "scopes": [
            # declare what permissions the service should have
            "list:users",  # list users
            "read:users:activity",  # read user last-activity
            "admin:servers",  # start/stop servers
        ],
    }
]

十、启动

(1)正常启动

创建启动脚本:

vim /etc/jupyterhub/start_jupyterhub.sh

写入以下内容:

nohup jupyterhub -f /etc/jupyterhub/jupyterhub_config.py > /dev/null 2>&1 &

赋予可执行权限:

chmod +x /etc/jupyterhub/start_jupyterhub.sh

然后执行脚本启动jupyterhub

/etc/jupyterhub/start_jupyterhub.sh

(2)设置开机自启动

若每次启动都需要手动运行脚本来启动是在太麻烦,所以我们将脚本添加到容器的自启动中,让其随着容器的启动而启动。

容器在启动时,会先执行/root/.bashrc文件,我们将要执行的脚本加入其中即可实现jupyterhub随容器的启动而启动

vim /root/.bashrc

添加以下内容:

if [ -f /etc/jupyterhub/start_jupyterhub.sh ]; then
      /etc/jupyterhub/start_jupyterhub.sh
fi

添加完成后,我们可以退出容器,然后让容器重启,看重启后jupyterhub是不是自动启动了

# 重启容器
docker resatrt jupyterhub

十一、访问

1、设置密码

在访问前先设置密码,root用户为管理员,docker中的root用户默认是没有密码的,需要我们设置一个:

passwd root

2、登录

然后再进行登录

用户登录:http://IP:8000/hub/login
用户管理:http://IP:8000/hub/admin

登录的密码是你系统用户的密码。若是要添加用户,在用户管理界面添加用户后,还需要在系统终端中修改密码。

登录界面

登陆后的jupyterlab界面:

管理界面:

十二、用户管理

1、单个或较少用户管理

(1)添加用户

使用root账户登录管理界面,然后点击Add Users添加用户,添加用户时候,每一行一个用户。可选择Admin设置添加的用户是否是管理员

添加后的界面如下:

(2)修改用户

添加用户后,可以点击Edit User进行用户的删除、修改用户名和赋予管理员权限等操作。

(3)修改和设置用户密码

jupyterhub无法在管理界面设置密码,设置密码需要在终端中进行设置。在jupyterhub终端中添加的用户,将被默认添加到系统用户中,并在/home文件夹下生成相应的用户目录:

因此,修改密码需要在终端中使用passwd命令来修改密码:

  • root用户可直接使用passwd 用户名来修改密码,且修改密码不需要知道当前的密码:

  • 普通用户只能够使用passwd修改自己的密码,且需要之前当前密码,密码也要设置8位及以上:

2、多用户批量管理

当需要有大量添加大量用户时,我们就需要使用chpasswd命令来批量修改密码

(1)添加用户

首先在管理面板中批量添加用户

(2)批量修改密码

然后将用户名和密码对应,写成用户名:密码的形式,存储在文件中,如存储在passwd.txt文件中,文件内容如下所示:

lab01:3200201137
lab02:3200204233
lab03:3190707121
lab04:3200201232
lab05:3201902211
lab06:3200209116
lab07:3211902229
lab08:3211901113
lab09:3190113205
lab10:3210204416
lab11:3210204328
lab12:3210204326
lab13:3210204314
lab14:3210204428
lab15:3210201309
lab16:3200204317
lab17:3201901231
lab18:3201901103
lab19:3201901107
lab20:3210201225

然后在终端执行以下命令,即可完成用户密码的批量修改

chpasswd < passwd.txt

这样添加的用户就可以通过用户名和设置的密码来访问了

十三、jupyterlab功能扩展

jupyterhub是用来管理多用户使用jupyterlab,但我们实际去写代码的界面其实还是jupyterlab。初始的jupyterlab功能十分有限,没有代码提示和自动补全、没有代码自动保存、没有代码格式化,所以我们需要通过安装插件来补全这些功能。jupyterlab插件有很多,这里介绍几个常用的。

1、中文界面

默认的jupyterlab是英文界面,我们需要安装插件来中文化

pip install jupyterlab-language-pack-zh-CN

安装后需要配置

2、自动保存

自动保存功能不需要安装插件,且jupyterlab是开启的,但jupyterlab中自动保存间隔是120秒,我们需要修改这个值。

  • 依次打开设置->高级设置编辑器->JSON设置编辑器

  • 然后添加自己的设置

3、自动闭合括号

设置->笔记本,勾选自动闭合括号

4、代码格式化

jupyterlab_code_formatter

# 安装插件
pip install jupyterlab_code_formatter
# 安装格式化工具
pip install black isort

该插件安装后需要重启才生效。

当我们写完代码后,点击如图所示的图标,代码就会被自动格式化:

5、树目录

jupyterlab-unfold

pip install jupyterlab-unfold

6、绘制可交互图

jupyterlab-matplotlib

pip install ipympl

该插件安装后,使用matplotlib绘图时只要加上以下代码,即可绘制可交互的图像:

%matplotlib widget

绘制的效果如下,可以点击图中的点查看对应数值,以及放大缩小图像等:

7、代码补全和自动提示

pip install jupyterlab-lsp python-lsp-server

安装后重启,重启完成后进入到jupyterlab界面,然后进行设置。

进入设置,选择Code Completion,勾选Continuous hinting后刷新界面即可

效果如下,和Pycharm等IDE提供的代码提示类似:

8、代码执行时间

pip install jupyterlab_execute_time

如图所示,可以看到上次执行代码的时间和执行耗时:

9、绘制流程图

pip install ipydrawio

安装重启后,在开始页,可以看到增加了两个选项,点击可以创建绘图

创建的绘图界面如下,和drawio相似,其实就是drawio的jupyterlab插件:

10、多用户设置同步问题

  • 当我们安装完插件后,需要进行一些设置才能够使用,但配置后我们发现只有当前用户可以使用,其他用户并没有进行配置。这是因为每个用户配置后相应的配置文件均保存在~/.jupyter文件夹下,若我们需要多个用户同时进行某项配置时,最简单的办法是直接使用配置好的用户的.jupyter文件夹替换要配置用户的文件夹即可,那样所有用户的配置都一样了。

  • 值得注意的是,替换文件夹后要配置相应的权限,以免替换后被替换的用户无法访问配置文件而无法加载。最简单的方法是以下设置:

    chmod -R 777 .jupyter
    
  • 当用户成百上千的时候,这么替换也属实麻烦,可以编写python或shell脚本去实现替换,以加快效率

十四、解决终端无法正常显示中文

1、安装locales

apt-get install locales -y

2、添加配置

dpkg-reconfigure locales

选择zh_CN.UTF-8 UTF-8

3、查看语言设置

locale

保证LANGzh_CN.UTF-8 UTF-8

若不是,可以添加环境变量

export LANG=zh_CN.UTF-8

追加到/etc/bash.bashrc文件中,然后再使其生效

source /etc/bash.bashrc

4、效果

设置完成后重新打开终端,设置成功

原来的显示

现在的显示

十五、解决matplotlib绘图异常

1、问题描述

matplotlib绘图代码如下:

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']

x=np.linspace(-np.pi,np.pi)
y1=np.sin(x)
y2=np.cos(x)
plt.title("常见三角函数")
plt.plot(x,y1,x,y2)
plt.show()

报错:

Font family [‘sans-serif‘] not found.Falling back to DejaVu Sans

原因:系统中缺少SimHei字体

2、问题解决

(1)获取matplotlib的字体目录

import patplotlib
print(matplotlib.matplotlib_fname())
/opt/miniconda3/lib/python3.9/site-packages/matplotlib/mpl-data/matplotlibrc

(2)打开字体目录

由上一步获取的地址修改得到

cd /opt/miniconda3/lib/python3.9/site-packages/matplotlib/mpl-data/fonts/ttf

(3)下载SimHei字体

下载地址:https://www.fontpalace.com/font-download/SimHei/

下载后复制到上一步得到的字体目录

(4)清除matplotlib缓存

# 先获取缓存路径
import matplotlib
matplotlib.get_cachedir()
'/root/.cache/matplotlib'
# 清除缓存
rm -rf /root/.cache/matplotlib

(5)修改配置文件

配置文件即第一步获取的文件

vim /opt/miniconda3/lib/python3.9/site-packages/matplotlib/mpl-data/matplotlibrc

修改的几处如下:

# 删除前面的#号
font.family:  sans-serif

# 删除前面的#号,并在后面添加SimHei
font.serif:    SimHei, DejaVu Serif, Bitstream Vera Serif, Computer Modern Roman, New Century Schoolbook, Century Schoolbook L, Utopia, ITC Bookman, Bookman, Nimbus Roman No9 L, Times New Roman, Times, Palatino, Charter, serif

# 将True盖为False
axes.unicode_minus: False

(6)重启

重启后再运行没问题了

十六、内存占用问题

  • 用户每打开一个Notebook文件,系统就会开始一个jupyter notebook内核进程,用户退出后进程不会自动终止;

  • jupyterhub虽然可以自动释放资源,但并不会释放jupyter notebook内核进程;

  • 当多个用户访问后,内存一直在增加,没有得到释放;

  • 暂时没有好的解决方法,只能够让jupyterhub容器定时重启;

    我们使用Linux中的crontab命令设置定时重启jupyterhub容器,crontab是Linux系统下用于执行定时任务的一个工具,用法可以自行百度。

    crontab -e
    

    添加以下字段:

    30 2 * * * docker restart jupyterhub
    

    此字段指定每天凌晨2点30分重启jupyterhub容器

  • 之后若有更好的办法再修改。

有关Linux部署JupyterHub实现多用户使用Jupyterlab的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

随机推荐