jupyter lab——可视化与便捷性的完美结合

本文主要介绍jupyter lab应用,它是一个在统计、数据分析和机器学习等领域广受好评的基于python的应用,同时也支持多种其他语言。

对于在校学生(可能更多地是研究生),尤其是实验室或者寝室有台式电脑,随身携带平板或者笔记本的同学们来说,如果能将台式电脑作为服务器,将jupyter架设在校园网或公网上,那么我们将会拥有一台高性能的服务器,并且可以随时随地的访问和使用。

基于这样的目的,本文将简单介绍jupyter的安装、配置、内网访问和公网访问等一系列需求和解决方案。

一、关于jupyter

1.1 简介

Jupyter源于Ipython Notebook,是使用Python(也有R、Julia、Node等其他语言的内核)进行代码演示、数据分析、可视化、教学的很好的工具,对Python的愈加流行和在AI领域的领导地位有很大的推动作用。

Jupyter Lab是Jupyter的一个拓展,提供了更好的用户体验,例如可以同时在一个浏览器页面打开编辑多个Notebook,Ipython console和terminal终端,并且支持预览和编辑更多种类的文件,如代码文件,Markdown文档,json,yml,csv,各种格式的图片,vega文件(一种使用json定义图表的语言)和geojson(用json表示地理对象),还可以使用Jupyter Lab连接Google Drive等云存储服务,极大得提升了生产力。

1.2 本地运行

一般来讲,jupyter lab的网页应用会默认运行在 http://localhost:8888 位置,用户可以在本地计算机通过浏览器访问网页使用jupyter相关服务。

可能大部分同学都只需要在单一电脑上使用jupyter服务,所以接下来将会主要讲解本机运行jupyter的相关内容。

1.2.1 Mac、Win操作系统

对于mac和win操作系统,最简便的使用jupyter的方式就是Anaconda。

相信了解python的同学对Anaconda都不会陌生,Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。是我们一般使用python语言进行数据科学探索的必备工具之一。

在Anaconda中包含了Jupyter lab和Jupyter notebook两个python套件。只要从官网下载并安装即可。

建议选择Python3.7的版本,并注意操作系统的选择。

Jupyter官方网站

-w669

安装完后Anaconda的界面如下:
-w1916

1.2.2 Linux操作系统

对于linux操作系统,同样我们也可以从官方网站直接下载Anaconda的安装包进行安装。

1
wget https://repo.anaconda.com/archive/Anaconda3-2018.12-Linux-x86_64.sh

如果不想安装anaconda,那么可以使用python包管理器直接安装jupyter lab或jupyter notbook。

1.首先验证linux服务器python版本和包管理器pip版本

1
2
3
4
python --version
python3 --version
pip -V
pip3 -V

2.根据相应版本安装jupyter,建议使用python3

1
2
3
4
5
6
7
# Python 2 的 notebook
sudo pip install jupyter
sudo pip install jupyterlab

# Python 3 的 notebook
sudo pip3 install jupyter
sudo pip3 install jupyterlab

3.最后,尝试在服务器本地启动 jupyter lab 应用。

1
jupyter notebook

4.如果终端看到下面的提示,就说明 notebook 启动成功了。

5.如果需要在后台启动,我们可以使用:

1
2
# 后台启动 notebook 服务
nohup jupyter lab &

这里nohup命令确保这个进程在断开 ssh 连接后依旧运行,& 让进程在后台运行。如果想终止 notebook 应用,请找到含有 jupyter 的进程,并用 kill 杀掉它。

可以使用:

1
2
ps -aux | grep jupyter
kill 任务ID(PID)

1.3 内网运行jupyter

1.3.1 使用密码加密jupyter lab

我们默认安装好的jupyter lab都是可以直接登陆的,但考虑到jupyter的功能强大,可以直接使用终端访问本地账户,而且我们的最终目的是希望将jupyter应用架设在校园局域网内甚至是公网内,这就对我们的应用安全有了更高的要求。我们可以考虑为jupyter加上密码保护,这样只有经过授权的用户才能访问jupyter。

对于密码而言,存储明文密码显然不是一个安全的做法。我们需要提供一个 hash 过的密码。登录时,notebook 应用获取用户提交的密码,进行 hash 计算,再与预先存储的值比对。如果两者相同,则认为用户提交的密码正确,予以放行。获取 hash 密码的方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 打开ipython
ipython

#只需复制In[1]:后的部分
In[1]: from IPython.lib import passwd

In[2]: passwd()

#输入密码并确认
Enter password:
Verify password:

#得到Hash值
Out[2]: 'sha1:e91aa8647e19:65adaefb90a7446283606eeae049af01fa050828'

#注意这里要复制上面的hash值,包括`sha1:`部分

这里我们得到了python给出的密码hash值:
sha1:e91aa8647e19:65adaefb90a7446283606eeae049af01fa050828

接下来我们需要配置jupyter应用
这里我们主要介绍通过jupyter config文件进行配置。

1.生成jupyter config文件

1
2
3
# 生成 /home/ipynb/.jupyter/jupyter_notebook_config.py 文件

jupyter notebook --generate-config

2.对jupyter_notebook_config.py文件进行修改

这个模板文件很长,但所有的内容都被注释掉了。可以直接在文档开头复制如下的内容,并进行相应的修改:

1
2
3
4
5
6
7
8
9
#------------------------------------------------------------------------------
# User configuration
#------------------------------------------------------------------------------
c.NotebookApp.ip = '*' # 允许从任意 IP 访问
c.NotebookApp.open_browser = False # 运行 notebook 应用时不打开浏览器
c.NotebookApp.password = u'sha1:e91aa8647e19:65adaefb90a7446283606eeae049af01fa050828' # 刚才生成的密码的 hash 值
c.NotebookApp.port = 28888 # 运行端口
c.NotebookApp.allow_remote_access = True #允许远程访问
c.NotebookApp.notebook_dir = '/Users/jupyter/' #jupyter默认根目录

关于Hash值,这里涉及到密码学的相关内容,如果希望有比较直观的了解,这里推荐两个小视频:

【官方双语】想知道比特币(和其他加密货币)的原理吗?

【官方双语】256位加密有多安全?


1.3.2 使用ssl协议加密

仅仅为 jupyter 设定密码并不能保障安全。如果密码在网络中以明文传输,就为中间人提供了截获的机会。稍有网络安全常识的人都知道,密码等敏感信息必须通过加密方式传输。因此,我们还需要提供 HTTPS 连接。

(1)没有域名的情况

对于HTTPS连接而言,如果我们没购买域名,那么可以直接使用openssl在本地生成一个秘钥对。

可以直接在~/.jupyter/文件夹下直接执行下面的命令:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mycert.pem -out mycert.pem

在.jupyter目录下我们会得到mycert.pemmycert.key两个文件。将这两个文件也加入到jupyter_notebook_config.py文件中。

1
2
3
4
5
6
7
8
9
10
11
#------------------------------------------------------------------------------
# User configuration
#------------------------------------------------------------------------------
c.NotebookApp.certfile = '/路径名/mycert.pem'
c.NotebookApp.keyfile = '/路径名/mycert.key'
c.NotebookApp.ip = '*' # 允许从任意 IP 访问
c.NotebookApp.open_browser = False # 运行 notebook 应用时不打开浏览器
c.NotebookApp.password = u'sha1:e91aa8647e19:65adaefb90a7446283606eeae049af01fa050828' # 刚才生成的密码的 hash 值
c.NotebookApp.port = 28888 # 运行端口
c.NotebookApp.allow_remote_access = True #允许远程访问
c.NotebookApp.notebook_dir = '/Users/jupyter/' #jupyter默认根目录

至此,我们配置好了jupyter应用,并且可以实现在内网使用任意IP进行访问,同时启用了密码和ssl安全协议。


openssl req命令主要的功能有,生成证书请求文件,查看验证证书请求文件,还有就是生成自签名证书。关于秘钥的相关问题有机会希望能单独开一篇文章进行学习和记录。

  • -new :说明生成证书请求文件
  • -x509 :说明生成自签名证书
  • -key :指定已有的秘钥文件生成秘钥请求,只与生成证书请求选项-new配合。
  • -newkey :-newkey是与-key互斥的,-newkey是指在生成证书请求或者自签名证书的时候自动生成密钥,然后生成的密钥名称由-keyout参数指定。当指定newkey选项时,后面指定rsa:bits说明产生rsa密钥,位数由bits指定。 如果没有指定选项-key和-newkey,默认自动生成秘钥。
  • -out:指定生成的证书请求或者自签名证书名称
    -nodes:如果指定-newkey自动生成秘钥,那么-nodes选项说明生成的秘钥不需要加密,即不需要输入passphase.

(2)有域名的情况

更进一步,如果我们是在服务器上进行jupyter的配置,那么我们完全可以利用云服务商提供的免费域名ssl证书,实现jupyter应用的加密访问。

接下来以阿里云为例,进行服务器端的jupyter应用域名绑定。

1.首先购买免费的ssl证书

-w1068

2.根据网页提示部署到云产品,也即为域名DNS添加一个.TXT的记录

3.下载秘钥对
-w237

4.采用第1.3.2节的方法,把下载到的秘钥对拷贝到.jupyter文件夹下,并修改jupyter conifg的相关路径。

5.在网页的DNS记录中添加一个指向服务器IP的A记录,注意这里可以是主域名也可以二级域名。

至此,服务器上的ssl加密设置就已经完成了。我们不但可以使用公网的IP(服务器IP)进行访问,还可以使用域名进行加密访问。(传说中的小绿锁)

1.4 公网访问jupyter应用

其实能够在内网中访问jupyter,已经足够我们日常生活和工作的需要了。因为一般来说对于校园网或者企业局域网都会有专门的VPN服务,当我们身处非校园网环境给的时候,我们可以比较便捷的通过VPN登录进校园网环境,然后通过内网IP访问jupyter服务。

但本着能折腾一下是一下和能偷懒就偷懒的精神,我们可能还是希望能够在公网下直接通过域名访问内网的应用。这其实就涉及到了内网穿透的相关问题。

也就是接下来我们要介绍的应可以实现内网穿透的frp工具。

二、关于frp

对于没有公网 IP 的内网用户来说,远程管理或在外网访问内网机器上的服务是一个问题。

FRP 全名:Fast Reverse Proxy。FRP 是一个使用 Go 语言开发的高性能的反向代理应用,可以帮助您轻松地进行内网穿透,对外网提供服务。FRP 支持 TCP、UDP、HTTP、HTTPS等协议类型,并且支持 Web 服务根据域名进行路由转发。

其主要作用如下:

  • 利用处于内网或防火墙后的机器,对外网环境提供 http 或 https 服务。
  • 对于 http, https 服务支持基于域名的虚拟主机,支持自定义域名绑定,使多个域名可以共用一个80端口。
  • 利用处于内网或防火墙后的机器,对外网环境提供 tcp 和 udp 服务,例如在家里通过 ssh 访问处于公司内网环境内的主机。

参考文章:

十分钟教你配置frp实现内网穿透

一款很好用的内网穿透工具—FRP

三、使用frp实现jupyter公网访问

如果想要实现内网穿透,那我们需要做的准备有:

  • 公网服务器1台(具有公网IP地址)
  • 内网主机1台(服务器或台式机均可)
  • 公网域名1个(非必须,但如果实现ssl加密访问则最好有域名)

3.1 安装frp

frp-Github主页

1
wget https://github.com/fatedier/frp/releases/download/v0.25.1/frp_0.25.1_linux_amd64.tar.gz

注意:

  • linux选amd64;
  • mac选freevbsd
  • win选windos_amd64

注意因为frp涉及到内网主机和公网主机,所以我们必须要在两台主机上同时下载并分别进行配置。

解压缩后我们会发现一系列文件。我们主要使用的就是 frpc.inifrps.ini这两个文件;

  • frpc.ini :客户端,即内网主机配置

  • frps.ini:服务器端,即公网服务器配置

3.2 配置公网服务器frps

1
2
3
4
5
6
7
8
9
$ vim frps.ini

[common]
bind_port = 7000
#默认配置中监听的是 7000 端口,可根据自己实际情况修改。
vhost_http_port = 8000
#设置内网转发而来的http应用的访问端口是 8000
vhost_https_port = 8001
#设置内网转发而来的https服务的端口是 8001
1
2
#启动 FRP 服务端
$ ./frps -c ./frps.ini

这样我们就在公网建立了一个能够接受内网转发的服务,并且为内网转发而来的支持不同协议的不同应用分别设置的相关的端口。

务必牢记去服务器安全组中放行这几个端口

3.3 配置内网主机frpc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ vim frpc.ini

[common]
# server_addr 为 FRP 服务端的公网 IP
server_addr = 4.3.2.1
# server_port 为 FRP 服务端监听的端口
server_port = 7000

#申请一个远程的 ssh 访问服务
[ssh]
#协议类型tcp
type = tcp
#本地ip
local_ip = 127.0.0.1
#本地服务所在端口(ssh shenjie@10.143.216.126默认端口)
local_port = 22
#在服务端上注册一个6000端口用于和本地22端口通信
remote_port = 6000


[jupyter]
#协议类型http
type = https
#本地服务所占用端口(对应你的jupyter端口)
local_port = 28888
#解析到公网服务器IP的域名(绑定好.TXT记录)
custom_domains = **.***.com
1
2
#启动 FRP 客户端
$ ./frpc -c ./frpc.ini

我们可以通过访问:https://\*.\*.com:8001来访问我们在内网主机上位于28888端口上的jupyter服务。

我们可以通过命令:ssh -p 6000 your_name@4.3.2.1通过ssh在任意公网登录内网主机。

至此我们就完成了在公网服务器上和内网主机上的frp内网穿透工作。

四、使用过程中遇到的问题

使用Firefox浏览器,使用域名+端口号形式访问jupyter lab,能够正常连接,但是无法运行命令,页面提示连接不到Kernel。log文件具体报错信息如下:

1
2
[I 18:52:24.668 LabApp] Adapting to protocol v5.1 for kernel c95d254f-7469-4b10-856a-2c41a930856f
[W 18:52:24.669 LabApp] 400 GET /api/kernels/c95d254f-7469-4b10-856a-2c41a930856f/channels?session_id=d3b0a731-5c34-46a9-8c56-f03b59d120a4 (127.0.0.1) 4.06ms referer=None

使用safari浏览器,可以正常运行。

解决方案:tornado降级至4.5.3,原始版本5.1.1
pip:
pip install tornado==4.5.3
conda:
conda install tornado==4.5.3