小白进阶之路|docker 搭建 jupyter notebook远程环境

前言 之前的文章说了服务器怎么搭建jupyter环境:https://blog.csdn.net/Qwertyuiop2016/article/details/85137644
但是我发现,这样配置有点麻烦不说,换个机器又要重新来一遍,能不能来个一劳永逸的方法?那肯定是docker了
官方镜像 官方文档:https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html
选择镜像 官方提供了几个镜像:

  1. jupyter/base-notebook
  2. jupyter/minimal-notebook
  3. jupyter/r-notebook
  4. jupyter/scipy-notebook
  5. jupyter/tensorflow-notebook
  6. jupyter/datascience-notebook
  7. jupyter/pyspark-notebook
  8. jupyter/all-spark-notebook
第一个为基础镜像,就是只包含基本的notebook功能。第二个在第一个的基础上安装了一些工具,具体装了啥可以看dockerfile。其他的就是安装了一些第三方Python库。我们自己搭建的话基本就是在第一个和第二个中选择
启动容器 docker命令就不细说了,请自行查阅:https://www.runoob.com/docker/docker-command-manual.html
  1. docker pull jupyter/base-notebook:latest 拉取镜像
  2. docker run --rm -p 8888:8888 jupyter/base-notebook:latest 运行镜像
Executing the command: jupyter notebook [I 19:31:09.573 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret [W 19:31:11.930 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended. [I 19:31:12.085 NotebookApp] JupyterLab alpha preview extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab [I 19:31:12.086 NotebookApp] JupyterLab application directory is /opt/conda/share/jupyter/lab [I 19:31:12.117 NotebookApp] Serving notebooks from local directory: /home/jovyan [I 19:31:12.117 NotebookApp] 0 active kernels [I 19:31:12.118 NotebookApp] The Jupyter Notebook is running at: [I 19:31:12.119 NotebookApp] http://[all ip addresses on your system]:8888/?token=3b8dce890cb65570fb0d9c4a41ae067f7604873bd604f5ac [I 19:31:12.120 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 19:31:12.122 NotebookApp]Copy/paste this URL into your browser when you connect for the first time, to login with a token: http://localhost:8888/?token=3b8dce890cb65570fb0d9c4a41ae067f7604873bd604f5ac

这只是测试一下,你可以浏览器访问一下最后一行格式的url,localhost换成服务器的ip,应该能正常访问,如果不能请开放服务器的防火墙和运营商的防火墙
3. 这样虽然能访问,但是我想将notebooks的根目录映射到本地。但是从上面的启动日志来看,默认的根目录在/home/jovyan,这个目录包含很多隐藏文件,映射时有些文件会报错,所以我们需要修改jupyter notebook的工作目录。
4. 修改设置参数的命令格式:docker run -p 8888:8888 jupyter/base-notebook start-notebook.sh --NotebookApp.password='sha1:74ba40f8a388:c913541b7ee99d15d5ed31d4226bf7838f83a50e'
就是在后面跟start-notebook.sh 然后在加上参数和值。
参数列表请看:https://jupyter-notebook.readthedocs.io/en/stable/config.html
挑几个我比较关心的参数:
  • NotebookApp.password:notebook访问密码
  • NotebookApp.allow_password_change:是否允许远程修改密码
  • NotebookApp.allow_remote_access:这个不知道是啥意思,反正我每次都加了
  • NotebookApp.open_browser:是否打开浏览器,这个在容器里默认就是False,所以可以不加
  • NotebookApp.notebook_dir:notebook工作目录
NotebookApp.password 后面不是跟的明文,需要运行下面两行Python代码设置之后,复制返回值
from notebook.auth import passwd
passwd()
5. 完整的docker命令
docker run -d \ -p 8888:8888 \ -v /var/jupyter:/home/jovyan/work \ --name jupyter \ jupyter/minimal-notebook:latest \ start-notebook.sh \ --NotebookApp.password='argon2:$argon2id$v=19$m=10240,t=10,p=8$zicxxxxxxxxxxxxxx4Q$+d1Sl9l+UvwRFc9CIPGPsg' \ --NotebookApp.allow_password_change=False \ --NotebookApp.allow_remote_access=True \ --NotebookApp.open_browser=False \ --NotebookApp.notebook_dir="/home/jovyan/work"

  1. 这里有个需要注意的,/home/jovyan/work目录是容器里的,而/var/jupyter是主机里的,需要你自己创建后修改所有者和所属组。当然,如果不想麻烦的话,直接在docker run -d 后面加上 --user root,它就会自动帮你修改。不修改的话,你会创建不了笔记,显示权限不足。
    mkdir /var/jupyter
    chown lighthouse:users /var/jupyter
    chmod 777 /var/jupyter 这一步应该是不需要的,不过设置了也没问题
增加插件和conda虚拟环境 小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

默认只有前三个File、Running和Clusters,我们可以安装插件和conda虚拟环境
插件的话只需要安装jupyter_contrib_nbextensions这个包就行,容器已经内置了conda,所以只需要让jupyter支持conda虚拟环境就行,安装nb_conda包就行。还有一个包yapf也需要安装,好像是命令自动补全的,有点忘了。
进入容器的命令:docker exec -it -u root jupyter bash -u root 表示以root启动,默认是jovyan
进入之后执行:conda install --yes yapf nb_conda jupyter_contrib_nbextensions
重启容器后生效:docker restart jupyter
小bug nb_conda一直有个bug没有修复
EnvironmentLocationNotFound: Not a conda environment: /opt/anaconda/envs/anaconda
解决方法:https://github.com/Anaconda-Platform/nb_conda/issues/66
简单来说就是把envmanager.py文件里的for env in info['envs']]修改为for env in info['envs'] if env != info['root_prefix']]
容器内这个文件的完整路径:/opt/conda/lib/python3.9/site-packages/nb_conda/envmanager.py
可以执行sed -i "s/info\['envs'\]\]/info['envs'] if env != info['root_prefix']]/g" /opt/conda/lib/python3.9/site-packages/nb_conda/envmanager.py这个命令替换
自定义镜像 上面启动容器之后还需要做一些操作,为什么不直接将这些操作打包成镜像呢,这样换一台机器也能直接启动,不需要修改任何东西
官方镜像的dockerfile文件:https://github.com/jupyter/docker-stacks
根据这些文件一眼就能看出minimal-notebook比base-notebook多了些什么,所以我们也根据base-notebook来修改我们的dockerfile。我去掉了他安装的git、vim等工具,如果你需要,可以自行加上。我其实就增加了后面两个RUN命令,第一个命令用来安装包,第二个用来修改envmanager.py文件。这里的mamba和conda是一样的,大概是conda的升级版
FROM jupyter/base-notebookUSER rootRUN apt-get update --yes && \ apt-get install --yes --no-install-recommends \ tzdata \ openssh-client \ inkscape \ libsm6 \ libxext-dev \ libxrender1 \ lmodern \ netcat \ texlive-xetex \ texlive-fonts-recommended \ texlive-plain-generic && \ apt-get clean && rm -rf /var/lib/apt/lists/*RUN mamba install --yes \ yapf \ nb_conda \ jupyter_contrib_nbextensions && \ mamba clean --all -f -y && \ fix-permissions "${CONDA_DIR}" && \ fix-permissions "/home/${NB_USER}"RUN sed -i "s/info\['envs'\]\]/info['envs'] if env != info['root_prefix']]/g" /opt/conda/lib/python3.9/site-packages/nb_conda/envmanager.pyUSER ${NB_UID}

将上面的内容保存为Dockerfile文件(无后缀名),接着在当前目录运行docker build -t kanade/jupyter:v1 . -t 后面是镜像名,随意指定(注意最后面有个小数点表示当前目录)。
启动的命令和上面的基本是一样的,只需要把jupyter/minimal-notebook:latest替换成kanade/jupyter:v1就行了
打包配置文件 上面创建的docker,还是需要在启动时指定参数,要不连配置参数也一起打包到镜像里
只需要在上面的dockerfile后面加
COPY jupyter_notebook_config.py /etc/jupyter/USER root# Prepare upgrade to JupyterLab V3.0 #1205 RUN sed -re "s/c.NotebookApp/c.ServerApp/g" \ /etc/jupyter/jupyter_notebook_config.py > /etc/jupyter/jupyter_server_config.py && \ fix-permissions /etc/jupyter/USER ${NB_UID}

其中jupyter_notebook_config.py就是notebook的配置文件,在dockerfile同目录下创建这个文件,内容如下(记得修改下面的密码):
import osc = get_config()# noqa: F821 c.NotebookApp.ip = "0.0.0.0" c.NotebookApp.port = 8888 c.NotebookApp.open_browser = False c.NotebookApp.password = 'argon2:$argon2id$v=19$m=10240,t=10,p=8$zicg2xxxxxxxxxxx$+d1Sl9l+UvwRFc9CIPGPsg' c.NotebookApp.allow_password_change = False c.NotebookApp.allow_remote_access = True c.NotebookApp.notebook_dir="/home/jovyan/work" # https://github.com/jupyter/notebook/issues/3130 c.FileContentsManager.delete_to_trash = Falseif "NB_UMASK" in os.environ: os.umask(int(os.environ["NB_UMASK"], 8))

那么在构建镜像的时候就会替换镜像里的默认配置,启动时也不需要加什么配置了。另外,默认的配置文件里有https证书的相关配置,因为我不需要证书,用http就行了,所以直接删除了那部分。
启动命令:docker run -d -p 8888:8888 -v /var/jupyter:/home/jovyan/work --name jupyter kanade/jupyter:v1
保存 要想在其他机器上使用这个容器,有很多方法,比如将镜像存为文件docker save -o jupyter.tar kanade/jupyter:v1。或者注册一个阿里云账号,推送到阿里云仓库等
JupyterLab 只需在容器加一个参数-e JUPYTER_ENABLE_LAB=yes,这样启动的就是JupyterLab,默认的是jupyter notebook
docker run -p 1024:8888 --rm -e JUPYTER_ENABLE_LAB=yes --name jupyterlab jupyter/base-notebook
或者在后面增加 start.sh jupyter lab
docker run -p 1024:8888 --rm --name jupyterlab jupyter/base-notebook start.sh jupyter lab
经过测试发现,上面的两个参数,仅仅是修改了默认访问的是notebook还是jupyterlab。其实即使你启动的是notebook,依旧可以访问jupyterlab,只需要把路径上的tree改成lab即可
自动补全 在notebook中自动补全只需要启用hinterland这个插件就会有实时的代码提示,而在jupyterlab中需要安装额外的插件。
插件地址:https://github.com/krassowski/jupyterlab-lsp
安装扩展:conda install jupyterlab-lsp或者pip install jupyterlab-lsp
小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

需要’jupyterlab>=3.0.0,<4.0.0a0 ',docker创建的jupyterlab应该是3.1,所以安装是没问题的。另外,这个只是主插件的库,还需要在网页上安装:Extension Manager(就是那个插件的图标,鼠标悬停可以显示文字)WARNING那一栏点击enable,并且搜索lsp,安装@krassowski/jupyterlab-lsp,最后一步就是安装Python的补全插件jedi-language-server,同样是pip或者conda都行。
如果想实时自动提示,Settings->Advanced Settings Editor->Code Completion 在右边的
User Preferences里的{}改成(不建议改左边的默认)
{ "continuousHinting": true, }

小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

中文 安装jupyterlab-language-pack-zh-CN, conda、pip应该都行,安装完之后应该能看到下图的中文,切换即可,如果没有可以重启容器。
小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

其他语言支持 小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

C++ github地址:https://github.com/jupyter-xeus/xeus-cling
使用conda或者mamba安装即可mamba install xeus-cling -c conda-forge, 安装完成就能看到和运行了
JavaScript github地址:https://github.com/n-riesco/ijavascript
运行下面两行就行了
npm install -g ijavascript
ijsinstall
Java github地址:https://github.com/SpencerPark/IJava
Java比较麻烦,需要安装jdk9+
add-apt-repository ppa:openjdk-r/ppa
apt-get update
apt install openjdk-11-jdk
docker 里默认没有add-apt-repository,百度一下怎么安装吧
接着在 https://github.com/SpencerPark/IJava/releases 下载ijava的zip文件,解压之后运行 python install.py --sys-prefix即可安装成功了
在jupyter里导包有三种方式:
  1. 导入本地包: %jars 本地绝对路径。导入的包必须是jar格式文件,或者是目录(默认导入目录下的所有jar)
  2. maven导入,以okhttp为例:%maven com.squareup.okhttp3:okhttp:3.10.0
  3. xml文件形式导入:
%%loadFromPOM com.squareup.okhttp3 okhttp 3.10.0

查看内核 jupyter kernelspec list 查看可用内核
jupyter kernelspec remove java 移除某个内核
打包 至于怎么将后面这些一起打包进镜像就不多说了,和之前的差不多。
【小白进阶之路|docker 搭建 jupyter notebook远程环境】小白进阶之路|docker 搭建 jupyter notebook远程环境
文章图片

打包完的镜像有点大,3.72G。怎么优化我暂时还不会,对docker仅仅是了解,边百度边使用。

    推荐阅读