JupyterHub in Docker:定制环境

目录

上一篇文章《JupyterHub In Docker:简单示例》介绍了使用 Docker 创建最简单的 JupyterHub 环境,为用户提供官方的 Jupyter 镜像。

本文进一步介绍如何为用户提供定制的 Jupyter 环境,并提供额外的功能。

概述

DockerSpawner 中可以配置使用的 Docker 镜像。

本文为 nwpc-oper/nwpc-graphics 项目构建 Docker 镜像,并内置 nwpc-oper/nwpc-data 库。

为了保存用户文件,将 notebook 目录使用 Docker volume 挂载,保证用户的数据不会丢失。

为了访问二级存储上的数据,需要将 /sstorage1 目录也同时挂载到 docker 容器中。

另外,绘图脚本因为版权问题,也无法直接放到 docker 容器中,所以也要挂载到容器中。

示意图

Hub 镜像

修改前一篇文章中 Hub 镜像的 jupyerhub_config.py 文件。

权限

使用 FirstUseAuthenticator 验证登录,用户在第一次登录时需要设置密码。

c.JupyterHub.authenticator_class = 'firstuseauthenticator.FirstUseAuthenticator'

notebook 镜像

使用下一节创建的 graphics-notebook 镜像。

c.DockerSpawner.image = 'graphics-notebook'

notebook 目录

设置暴露给用户的 notebook 目录。 本文的 notebook 镜像基于jupyter/docker-stacks 系列镜像构建,使用的用户名均为 jovyan。 所以 notebook 目录可以设置为 '/home/jovyan/work'

import os

notebook_dir = os.environ.get('DOCKER_NOTEBOOK_DIR') or '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir

挂载

设置目录挂载。

有两种形式:

  • volume 挂载:推荐将用户数据保存到单独的 volume 中。
  • 目录绑定:推荐仅使用只读方式挂载

下面的代码中使用 volume 方式挂载 notebook 目录,并使用只读目录绑定方式挂载程序目录和数据目录。

c.DockerSpawner.volumes = { 
    'jupyterhub-user-{username}': notebook_dir,
    "/home/wangdp/project/graphics/operation/system": {
        "bind": "/srv/system",
        "mode": "ro",
    },
    "/sstorage1": {
        "bind": "/sstorage1",
        "mode": "ro",
    }
}

Notebook 镜像

基于 jupyter/base-notebook 构建新的镜像,安装 nwpc-datanwpc-graphics 库,并安装绘图需要的 ncl 和 imagemagick 库。 设置环境变量 NWPC_GRAPHICS_CONFIG

FROM jupyter/base-notebook:latest

COPY lib /srv/lib

RUN cd /srv/lib/nwpc-data && \
    python3 -m pip install . && \
    cd /srv/lib/nwpc-graphics && \
    python3 -m pip install .

RUN conda install -c conda-forge -y ncl imagemagick

ENV NWPC_GRAPHICS_CONFIG /srv/lib/nwpc-graphics/tool/docker/config/config.yaml

WORKDIR /srv

构建镜像,并命名为 graphics-notebook

sudo docker build \
  --rm \
  -t graphics-notebook \
  .

运行

运行方法与前一篇文章一样。

sudo docker run \
  --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --net jupyterhub \
  --name jupyterhub \
  -p 9500:8000 \
  hub

使用 nwp 用户登录后,从 Portainer 中可以看到有新的容器被创建

同时有新的 volume 被创建

如果 volume 已存在,则会直接使用,这样就保证用户数据不会丢失。

参考

https://jhubdocs.readthedocs.io/en/latest/dockerspawner/README.html#configuration

JupyterHub In Docker:简单示例