Skip to content

Commit 9bfdd5e

Browse files
committed
Extend advanced JupyterLab customizations
1 parent a674b61 commit 9bfdd5e

File tree

2 files changed

+150
-76
lines changed

2 files changed

+150
-76
lines changed

topics/teaching/tutorials/jbt-customization-1/tutorial.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: tutorial_hands_on
33

4-
title: Basics of JupyterLab customization
4+
title: Basic JupyterLab customizations
55
subtopic: practises
66
draft: true
77
time_estimation: 1h

topics/teaching/tutorials/jbt-customization-2/tutorial.md

Lines changed: 149 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,162 @@
11
---
22
layout: tutorial_hands_on
33

4-
title: Advanced Jupyter customization
4+
title: Advanced JupyterLab customizations
55
subtopic: practises
66
draft: true
77
time_estimation: 90m
88
questions:
9-
- How can I tailor Jupyter to my specific teaching needs?
9+
- How can I tailor JupyterLab to my specific teaching needs?
1010
objectives:
11-
- A guide to advanced Jupyter customization is provided, e.g. how to install proxy applications.
11+
- A guide to advanced JupyterLab customization is provided, e.g. how to install kernels and proxy applications.
1212
key_points:
13-
- Advanced customitzations may be time-consuming, but offer great potential and reusability value.
13+
- Advanced customitzations may be time-consuming, but offer many possibilities and reusability value.
1414
contributors:
1515
- mittler-works
1616
---
1717

18-
# Introduction
19-
20-
Now we know how to include changes, we will build something more complex and look at some pitfalls.
21-
22-
# Install an additional Kernel
23-
24-
https://github.com/jupyter/jupyter/wiki/Jupyter-kernels
25-
26-
Rust: https://github.com/evcxr/evcxr/tree/main/evcxr_jupyter
27-
28-
29-
```
30-
FROM quay.io/jupyter/minimal-notebook:2025-06-23
31-
32-
USER root
33-
RUN apt update \
34-
&& apt install -y build-essential \
35-
&& apt clean
36-
37-
USER ${NB_USER}
38-
ADD --chmod=755 https://sh.rustup.rs /tmp/rustup.sh
39-
RUN /tmp/rustup.sh -v -y
40-
RUN . "$HOME/.cargo/env" && cargo install --locked evcxr_jupyter
41-
RUN . "$HOME/.cargo/env" && evcxr_jupyter --install
42-
```
43-
44-
Build It.
45-
46-
Run it.
47-
48-
Try it out:
49-
50-
```rust
51-
println!("Hello World!");
52-
```
53-
54-
HINT:
55-
56-
This method installs all the kernel related resources inside the default homedir.
57-
58-
Therefore this will not work inside deployments where an empty volume is mounted as homedir, e.g. in default z2jh JupyterHub Deployments.
59-
60-
# Config Changes
61-
62-
* Where to put them
63-
You may put it in `~/.jupyter/jupyter_lab_config.py`
64-
65-
But you should put it in `/etc/jupyter/jupyter_lab_config.py` because homedir will be overriden in some infrastructures.
66-
67-
68-
* What to put there
69-
https://docs.jupyter.org/en/latest/use/config.html
70-
71-
You find all configuration options here: https://jupyter-server.readthedocs.io/en/latest/other/full-config.html
72-
73-
* How to put there
74-
Create a new local file `jupyter_lab_config.py` and fill it with content.
75-
76-
Then, in your Dockerfile add it either as system wide config (/etc) or user config (~/)
77-
78-
```dockerfile
79-
FROM quay.io/jupyter/minimal-notebook:2025-06-23
80-
81-
COPY --chown=root:root jupyter_lab_config.py /etc/jupyter/jupyter_lab_config.py
82-
83-
```
18+
# Prerequisites
19+
20+
It is assumed that you either completed the previous tutorial "Basic JupyterLab customizations" or that you already have basic knowledge of containerization and JupyterLab customizing.
21+
22+
With this knowledge, we'll add some more advanced customizations to JupyterLab and look at some pitfalls.
23+
24+
# Installing an additional Kernel
25+
26+
One common szenario for customization is the need for an additional kernel, e.g. for Julia or R. This tutorial guides you through installing a rust kernel on top of `minimal-notebook` as an example.
27+
28+
> <comment-title>Jupyter Kernels</comment-title>
29+
>
30+
> A list of availible Jupyter Kernels can be found at [https://github.com/jupyter/jupyter/wiki/Jupyter-kernels](https://github.com/jupyter/jupyter/wiki/Jupyter-kernels)
31+
{: .comment}
32+
33+
If you look for `Rust` you'll find the `Evcxr` Jupyter Kernel which is the one we are going to add.
34+
35+
> <comment-title>Evcxr Kernel</comment-title>
36+
>
37+
> All relevant information for the Evcxr Kernel can be found at [https://github.com/evcxr/evcxr/tree/main/evcxr_jupyter](https://github.com/evcxr/evcxr/tree/main/evcxr_jupyter)
38+
{: .comment}
39+
40+
> <hands-on-title></hands-on-title>
41+
>
42+
> Create a new directory. Inside, create a `Dockerfile` with the following content:
43+
>
44+
> ```
45+
> FROM quay.io/jupyter/minimal-notebook:2025-06-23
46+
>
47+
> USER root
48+
> RUN apt update \
49+
> && apt install -y build-essential \
50+
> && apt clean
51+
>
52+
> USER ${NB_UID}
53+
> ADD --chmod=755 https://sh.rustup.rs /tmp/rustup.sh
54+
> RUN /tmp/rustup.sh -v -y
55+
>
56+
> ENV PATH="${PATH}:${HOME}/.cargo/bin"
57+
> RUN cargo install --locked evcxr_jupyter
58+
> RUN evcxr_jupyter --install
59+
> ```
60+
{: .hands_on}
61+
62+
> <comment-title>Breakdown</comment-title>
63+
>
64+
> Again, we are using `minimal-notebook` as base image. But this time we need to do more than just installing a python package:
65+
> 1. we need to install system packages to meet requirements for Rust
66+
> 2. we need to install Rust itself
67+
> 3. we need to install and register the Evcxr kernel
68+
>
69+
> In order to install system packages, we need a privileged user inside the docker build, which is why we are changing to the root user using the `USER` keyword. When installing packages, keep in mind that docker builds are non-interactive, thus you need to use the `-y` flag to bypass the confirmation prompt.
70+
>
71+
> After installing system files, we can return to the JupyterLab default user, who is usually called `jovyan`. The variable `NB_UID` is inherited from the base image.
72+
>
73+
> Next, the rustup utility will be downloaded and executed. Note, with the `--chmod` portion you can tell `ADD` in which filemod to save the downloaded file, thus you do not need to make the file executable in a separate step.
74+
> The rustup script installs the binaries for rust in `${HOME}/.cargo/bin` which is why we need to add it to the path. We can do that simply by using the `ENV` keyword.
75+
>
76+
> At least, we install and register the Evcxr as explained on the projects github page.
77+
{: .question}
78+
79+
> <hands-on-title>Build your JupyterLab</hands-on-title>
80+
>
81+
> ```bash
82+
> sudo docker build -t my-rust-jupyterlab .
83+
> ```
84+
{: .hands_on}
85+
86+
> <hands-on-title>Run your JupyterLab</hands-on-title>
87+
>
88+
> ```bash
89+
> sudo docker run --rm -p 127.0.0.1:8888:8888 my-rust-jupyterlab .
90+
> ```
91+
{: .hands_on}
92+
93+
> <hands-on-title>Try your JupyterLab</hands-on-title>
94+
>
95+
> Again, you'll be provided with a link to open your JupyterLab.
96+
>
97+
> Open it, click on the Rust kernel and run following snippet:
98+
> ```rust
99+
> println!("Hello World!");
100+
> ```
101+
{: .hands_on}
102+
103+
Congratulations, you have successfully installed a custom kernel to your JupyterLab!
104+
105+
# Configuration Changes
106+
107+
There are a few files for configuring JupyterLab. One important one is the `jupyter_lab_config.py` file, where you can configure various different settings, e.g. the log level of the server application and much more.
108+
109+
> <comment-title></comment-title>
110+
>
111+
> All relevant configuration options for `jupyter_lab_config.py` can be found at [https://jupyter-server.readthedocs.io/en/latest/other/full-config.html](https://jupyter-server.readthedocs.io/en/latest/other/full-config.html)
112+
{: .comment}
113+
114+
You might include this file either as a user configuration in the user's home directory like this: `${HOME}/.jupyter/jupyter_lab_config.py`. But you better include it as a system-wide configuration by including it as `/etc/jupyter/jupyter_lab_config.py`. You can find out why this is the better solution in the [persistent data](#persistent-data) section.
115+
116+
> <hands-on-title>Include your custom configuration</hands-on-title>
117+
>
118+
> First, create a snippet of custom config, e.g. let's edit the default name for Notebooks from "Untitled" to "HelloWorld". Save it as `jupyter_lab_config.py`:
119+
>
120+
> ```python
121+
> c.ContentsManager.untitled_notebook = 'HelloWorld'
122+
> ```
123+
>
124+
> Then, add it as system wide config to your Dockerfile. Again, we're using the `minimal-notebook` as our base image:
125+
>
126+
> ```dockerfile
127+
> FROM quay.io/jupyter/minimal-notebook:2025-06-23
128+
>
129+
> COPY --chown=root:root jupyter_lab_config.py /etc/jupyter/jupyter_lab_config.py
130+
> ```
131+
>
132+
> You may now build it as usual...
133+
>
134+
> ```bash
135+
> sudo docker build -t my-configured-jupyterlab .
136+
> ```
137+
>
138+
> ...run it as usual...
139+
>
140+
> ```bash
141+
> sudo docker run --rm -p 127.0.0.1:8888:8888 my-configured-jupyterlab .
142+
> ```
143+
>
144+
> ...and access it with the printed URL. Now, open a new Notebook Document and you'll see it is now called `HelloWorld.ipynb` instead of `Untitled.ipynb`.
145+
{: .hands_on}
146+
147+
Congratulations, you have successfully configured your JupyterLab with a custom configuration! While this example handles a very low impact customization, please review the available configuration options! You may also configure plugins that way, as you will learn later in the [Application Proxies](#application-proxies) section.
84148
85149
# Persistent Data
86150
87-
* HomeDir will be overlayed with a mounted Volume
151+
Even though persistent data is not strictly a topic of customization, it is a relevant topic that you have to keep in mind when customizing your JupyterLab.
88152
89-
* WIP
153+
Running JupyterLab in a container, means that your data may be lost when the container is removed. To avoid data loss, volumes can be used.
90154
91-
## External persistent Data
155+
--> On local machine, mount it wherever you want
92156
93-
* Depends on your environment
157+
--> Bind mount vs actual volume
94158
95-
* WIP
159+
--> With JupyterHub it's common to overlay homedir
96160
97161
## Large Data
98162
@@ -104,6 +168,8 @@ COPY --chown=root:root jupyter_lab_config.py /etc/jupyter/jupyter_lab_config.py
104168
105169
## Sensitive Data (?)
106170
171+
* Just avoid at all cost
172+
107173
* Maybe WIP, but maybe put that into `jbt-intro`
108174
109175
# Application Proxies
@@ -176,6 +242,14 @@ Why is the rust installation in step 1 of this tutorial problematic in case this
176242

177243
--> it installs rust in homedir
178244

245+
246+
HINT:
247+
248+
This method installs all the kernel related resources inside the default homedir.
249+
250+
Therefore this will not work inside deployments where an empty volume is mounted as homedir, e.g. in default z2jh JupyterHub Deployments.
251+
252+
179253
Build a Customized JupyterLab with an available rust kernel even in JupyterHub szenario.
180254

181255
```dockerfile

0 commit comments

Comments
 (0)