How to Create a Custom Docker Image for JupyterHub
A custom Docker image lets you start JupyterHub with the Python libraries and tools you need already installed. This guide shows the basic workflow: create a Dockerfile, install packages, build the image, push it to Docker Hub, then select it from JupyterHub using the Other image option.
1. Start with a Base Image¶
Create a file named Dockerfile and start from an existing Jupyter image. For most Python notebooks, scipy-notebook is a good base image because it already includes Jupyter and common scientific Python packages.
FROM quay.io/jupyter/scipy-notebook:2025-01-28Use a dated image tag instead of latest so your environment is reproducible.
2. Add Required Packages¶
Add the Python libraries or system tools your class or project needs. This example installs seaborn for visualization and openpyxl for reading and writing Excel .xlsx files.
FROM quay.io/jupyter/scipy-notebook:2025-01-28
RUN pip install \
--no-cache-dir \
seaborn \
openpyxlYou can replace these packages with the libraries you need, such as plotly, geopandas, tensorflow, or course-specific packages.
3. Build the Image¶
Run the build command from the same folder where your Dockerfile is saved. Replace yourusername with your Docker Hub username.
docker build -t yourusername/jhub-custom:1.0 .The tag 1.0 gives you a version you can reuse later in JupyterHub. When you update the Dockerfile, build a new tag such as 1.1.
4. Push to Docker Hub¶
Log in to Docker Hub, then push the image.
docker login
docker push yourusername/jhub-custom:1.0For the easiest JupyterHub setup, use a public Docker Hub repository unless private registry credentials have already been configured for the hub.
5. Use the Image in JupyterHub¶
Paste the full image name into the Other image field on the JupyterHub Server Options page.
docker.io/yourusername/jhub-custom:1.0Go to the Create Server page.
Adjust any hardware resources, such as CPUs, RAM, or GPUs.
Click the dropdown under Notebook Container Image.

Select Other from the list.

Paste your Docker image URL.

6. Start Your Notebook¶
Click Start Server. JupyterHub will pull your custom image and start a notebook environment with your packages installed.
After the server starts, you can verify the example packages in a notebook cell:
import seaborn
import openpyxl
print("Custom image packages loaded")Important Notes¶
Start from an existing Jupyter image to help ensure compatibility with JupyterHub.
Use a public Docker Hub repository unless registry credentials are configured.
Use versioned tags such as
1.0,1.1, or a date-based tag so you can update the image later.Avoid putting passwords, API keys, tokens, or student data inside the Docker image.
If your image fails to start, test it locally first and confirm that the package install step completed successfully.
Supported Docker Image URL Formats¶
The Other image field accepts common image names and registry URLs, including:
yourusername/jhub-custom:1.0docker.io/yourusername/jhub-custom:1.0ghcr.io/yourorg/jhub-custom:1.0
When possible, use the full registry path, such as docker.io/yourusername/jhub-custom:1.0, so it is clear where JupyterHub should pull the image from.