JupyterHub ML Environment
JupyterHub with GPU support for ML.
Overview
JupyterHub is a multi-user server that spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. Originally developed to serve computational environments for hundreds of users in educational and research settings, JupyterHub enables organizations to provide centralized access to Jupyter notebooks while maintaining user isolation and resource management. It supports various authentication methods and can spawn user environments in Docker containers, making it ideal for data science teams and ML workflows.
This deployment creates a complete JupyterHub infrastructure with three core services: the main JupyterHub server for user management and notebook spawning, a PostgreSQL database (jupyterhub-db) for persistent storage of user data and hub state, and an NGINX reverse proxy for load balancing and SSL termination. The configuration includes Docker socket mounting to enable JupyterHub's DockerSpawner functionality, allowing it to create isolated containers for each user session with potential GPU access for machine learning workloads.
This stack is perfect for data science teams, educational institutions, and research organizations that need to provide multiple users with consistent, isolated Jupyter environments. The combination of JupyterHub's multi-user capabilities, PostgreSQL's robust data persistence, and NGINX's high-performance proxying creates a production-ready platform for collaborative data science and machine learning development with the flexibility to scale from small teams to hundreds of concurrent users.
Key Features
- Multi-user Jupyter notebook server with user isolation and resource management
- DockerSpawner integration for containerized user environments with GPU support capability
- PostgreSQL backend for persistent storage of user data, hub state, and session management
- NGINX reverse proxy with load balancing and SSL termination support
- Configurable authentication backends including OAuth, LDAP, PAM, and custom authenticators
- Admin interface for user management, server control, and resource monitoring
- Customizable user environments through Docker images with pre-installed ML libraries
- Volume mounting support for shared datasets and collaborative workspaces
Common Use Cases
- 1Data science teams requiring shared computational environments with version-controlled notebooks
- 2Educational institutions providing students with consistent Python/R environments for coursework
- 3Research organizations needing multi-user access to GPU resources for deep learning experiments
- 4Corporate ML teams sharing datasets and models across different projects and users
- 5Training workshops and bootcamps requiring instant notebook access for participants
- 6Remote development teams needing centralized Jupyter environments with persistent storage
- 7Organizations migrating from individual Jupyter installations to centralized management
Prerequisites
- Docker Engine with minimum 4GB RAM allocated for user containers and ML workloads
- Port 8000 available for JupyterHub web interface and port 80 for NGINX proxy
- Custom jupyterhub_config.py file configured with desired authentication and spawner settings
- NGINX configuration file (nginx.conf) with proper upstream and SSL settings
- Environment variables set for DB_PASSWORD and optional JUPYTER_PORT/NGINX_PORT customization
- Understanding of Docker container management and JupyterHub administration concepts
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 jupyterhub: 3 image: jupyterhub/jupyterhub:latest4 container_name: jupyterhub5 restart: unless-stopped6 ports: 7 - "${JUPYTER_PORT:-8000}:8000"8 environment: 9 - POSTGRES_HOST=jupyterhub-db10 - POSTGRES_DB=jupyterhub11 - POSTGRES_USER=jupyterhub12 - POSTGRES_PASSWORD=${DB_PASSWORD}13 volumes: 14 - jupyterhub_data:/srv/jupyterhub15 - /var/run/docker.sock:/var/run/docker.sock16 - ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro17 depends_on: 18 - jupyterhub-db1920 jupyterhub-db: 21 image: postgres:15-alpine22 container_name: jupyterhub-db23 restart: unless-stopped24 environment: 25 - POSTGRES_USER=jupyterhub26 - POSTGRES_PASSWORD=${DB_PASSWORD}27 - POSTGRES_DB=jupyterhub28 volumes: 29 - jupyter_db_data:/var/lib/postgresql/data3031 nginx: 32 image: nginx:alpine33 container_name: jupyter-nginx34 restart: unless-stopped35 ports: 36 - "${NGINX_PORT:-80}:80"37 volumes: 38 - ./nginx.conf:/etc/nginx/nginx.conf:ro3940volumes: 41 jupyterhub_data: 42 jupyter_db_data: .env Template
.env
1# JupyterHub2JUPYTER_PORT=80003DB_PASSWORD=jupyterhub_password4NGINX_PORT=80Usage Notes
- 1Docs: https://jupyterhub.readthedocs.io/
- 2JupyterHub at http://localhost:8000 - multi-user notebook server
- 3Configure jupyterhub_config.py for authentication (OAuth, LDAP, PAM)
- 4Use DockerSpawner for isolated user containers with GPU support
- 5Mount shared datasets at /srv/data or use NFS for collaboration
- 6Pre-install libraries in custom Docker images for users
Individual Services(3 services)
Copy individual services to mix and match with your existing compose files.
jupyterhub
jupyterhub:
image: jupyterhub/jupyterhub:latest
container_name: jupyterhub
restart: unless-stopped
ports:
- ${JUPYTER_PORT:-8000}:8000
environment:
- POSTGRES_HOST=jupyterhub-db
- POSTGRES_DB=jupyterhub
- POSTGRES_USER=jupyterhub
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- jupyterhub_data:/srv/jupyterhub
- /var/run/docker.sock:/var/run/docker.sock
- ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro
depends_on:
- jupyterhub-db
jupyterhub-db
jupyterhub-db:
image: postgres:15-alpine
container_name: jupyterhub-db
restart: unless-stopped
environment:
- POSTGRES_USER=jupyterhub
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=jupyterhub
volumes:
- jupyter_db_data:/var/lib/postgresql/data
nginx
nginx:
image: nginx:alpine
container_name: jupyter-nginx
restart: unless-stopped
ports:
- ${NGINX_PORT:-80}:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 jupyterhub:5 image: jupyterhub/jupyterhub:latest6 container_name: jupyterhub7 restart: unless-stopped8 ports:9 - "${JUPYTER_PORT:-8000}:8000"10 environment:11 - POSTGRES_HOST=jupyterhub-db12 - POSTGRES_DB=jupyterhub13 - POSTGRES_USER=jupyterhub14 - POSTGRES_PASSWORD=${DB_PASSWORD}15 volumes:16 - jupyterhub_data:/srv/jupyterhub17 - /var/run/docker.sock:/var/run/docker.sock18 - ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py:ro19 depends_on:20 - jupyterhub-db2122 jupyterhub-db:23 image: postgres:15-alpine24 container_name: jupyterhub-db25 restart: unless-stopped26 environment:27 - POSTGRES_USER=jupyterhub28 - POSTGRES_PASSWORD=${DB_PASSWORD}29 - POSTGRES_DB=jupyterhub30 volumes:31 - jupyter_db_data:/var/lib/postgresql/data3233 nginx:34 image: nginx:alpine35 container_name: jupyter-nginx36 restart: unless-stopped37 ports:38 - "${NGINX_PORT:-80}:80"39 volumes:40 - ./nginx.conf:/etc/nginx/nginx.conf:ro4142volumes:43 jupyterhub_data:44 jupyter_db_data:45EOF4647# 2. Create the .env file48cat > .env << 'EOF'49# JupyterHub50JUPYTER_PORT=800051DB_PASSWORD=jupyterhub_password52NGINX_PORT=8053EOF5455# 3. Start the services56docker compose up -d5758# 4. View logs59docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/jupyter-ml-stack/run | bashTroubleshooting
- JupyterHub fails to start with 'database connection failed': Verify jupyterhub-db container is running and DB_PASSWORD environment variable matches between services
- Users cannot spawn notebooks with 'spawn failed' error: Check that Docker socket is properly mounted and JupyterHub has permissions to create containers
- NGINX returns 502 Bad Gateway: Ensure JupyterHub container is healthy and accessible on port 8000, verify nginx.conf upstream configuration
- PostgreSQL data loss after container restart: Confirm jupyter_db_data volume is properly mounted and persistent
- Out of memory errors during notebook execution: Increase Docker memory limits and configure resource limits in jupyterhub_config.py
- Authentication loops or login failures: Review jupyterhub_config.py authentication settings and ensure proper authenticator configuration
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
jupyterhubpostgresnginx
Tags
#jupyter#ml#data-science#notebooks
Category
AI & Machine LearningAd Space
Shortcuts: C CopyF FavoriteD Download