Configuring JupyterLab or JupyterHub with LabNow AI Docker Images: A Complete Guide
LabNow AI Docker images provide pre-configured Ubuntu-based containers with Conda-managed Python 3.12, enabling single-command deployment of JupyterLab or JupyterHub environments through minimal Dockerfile extensions and standard docker run commands.
The labnow-ai/lab-foundation repository supplies a modular stack of container images that eliminate environment configuration overhead when configuring JupyterLab or JupyterHub with LabNow AI Docker images. Each layer—from the base OS to optional CUDA drivers—is engineered to support immediate scientific computing workloads without manual dependency resolution.
Architectural Overview of the LabNow AI Image Stack
The foundation repository organizes containers into four distinct layers. Understanding this hierarchy ensures you select the optimal base for your specific Jupyter deployment.
OS Layer: labnow/atom
Built from docker_atom/Dockerfile, this layer provides the Ubuntu Noble base system with essential OS packages, locale configuration, and sudo setup. It serves as the immutable foundation for all downstream images.
Python and Conda Layer: labnow/base
Constructed via docker_base/Dockerfile, this image inherits from labnow/atom and installs Miniconda alongside Python 3.12. It includes the uv fast installer and optionally replaces the system Python with the Conda-managed version, creating a self-contained runtime for scientific libraries.
GPU Acceleration Layer: labnow/cuda
For workloads requiring NVIDIA GPUs, docker_cuda/nvidia-cuda.Dockerfile extends the base image with proprietary driver libraries and the CUDA toolkit. This layer maintains compatibility with the Conda environment while exposing GPU hardware to containers.
Application Layer: Your Custom Configuration
The final layer is your responsibility. By creating a thin Dockerfile that references one of the LabNow base images, you install Jupyter components, configure networking, and expose service ports without managing OS-level dependencies.
Configure JupyterLab for Single-User Notebooks
To deploy a personal JupyterLab instance, extend labnow/base with the server application and network configuration.
Create a Dockerfile in your project root:
# Use the LabNow base image containing Conda + Python 3.12
FROM labnow/base:latest
LABEL maintainer="postmaster@labnow.ai"
# Install JupyterLab and generate default configuration
RUN pip install --no-cache-dir jupyterlab notebook && \
jupyter lab --generate-config && \
echo "c.ServerApp.ip = '0.0.0.0'" >> /root/.jupyter/jupyter_server_config.py && \
echo "c.ServerApp.open_browser = False" >> /root/.jupyter/jupyter_server_config.py && \
echo "c.ServerApp.port = 8888" >> /root/.jupyter/jupyter_server_config.py && \
echo "c.ServerApp.token = 'YOUR_TOKEN_HERE'" >> /root/.jupyter/jupyter_server_config.py
EXPOSE 8888
CMD ["jupyter", "lab"]
Build and run the container:
docker build -t labnow/jupyterlab:latest .
docker run -d --name jlab -p 8888:8888 labnow/jupyterlab:latest
Access the environment at http://localhost:8888 using the token specified in the configuration. Because docker_base/Dockerfile already established the Conda environment, additional packages install via conda install or pip install without compiler errors.
Deploy JupyterHub for Multi-User Environments
For team-based deployments, configure JupyterHub by installing the hub application and proxy on the same base image.
Create a dedicated Dockerfile:
FROM labnow/base:latest
LABEL maintainer="postmaster@labnow.ai"
# Install JupyterHub and configurable HTTP proxy
RUN pip install --no-cache-dir jupyterhub configurable-http-proxy && \
echo "c.JupyterHub.bind_url = 'http://0.0.0.0:8000'" > /opt/jupyterhub_config.py && \
echo "c.JupyterHub.logo_file = ''" >> /opt/jupyterhub_config.py
EXPOSE 8000
CMD ["jupyterhub", "-f", "/opt/jupyterhub_config.py"]
Execute the build and deployment:
docker build -t labnow/jupyterhub:latest .
docker run -d --name jhub -p 8000:8000 labnow/jupyterhub:latest
Navigate to http://localhost:8000 to access the multi-user interface. Production deployments should mount a persistent volume containing a full jupyterhub_config.py and database backend; the LabNow image provides the core runtime, leaving orchestration decisions to your infrastructure team.
Enable GPU Support for CUDA Workloads
When configuring JupyterLab for deep learning, inherit from labnow/cuda to leverage NVIDIA GPUs.
FROM labnow/cuda:latest
LABEL maintainer="postmaster@labnow.ai"
# Install JupyterLab and PyTorch with CUDA support
RUN pip install --no-cache-dir jupyterlab \
torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu121 && \
jupyter lab --generate-config && \
echo "c.ServerApp.ip = '0.0.0.0'" >> /root/.jupyter/jupyter_server_config.py && \
echo "c.ServerApp.open_browser = False" >> /root/.jupyter/jupyter_server_config.py && \
echo "c.ServerApp.port = 8888" >> /root/.jupyter/jupyter_server_config.py
EXPOSE 8888
CMD ["jupyter", "lab"]
Execute with GPU access enabled:
docker run -d --gpus all -p 8888:8888 labnow/jupyterlab-gpu:latest
The --gpus all flag delegates host NVIDIA drivers to the container, while the underlying docker_cuda/nvidia-cuda.Dockerfile ensures compatibility with the CUDA toolkit and Conda-managed Python.
Key Source Files in labnow-ai/lab-foundation
| File | Purpose | Location |
|---|---|---|
docker_atom/Dockerfile |
Ubuntu Noble base, locale, sudo, and utility scripts in /opt/utils |
docker_atom/Dockerfile |
docker_base/Dockerfile |
Miniconda installation, Python 3.12, uv installer, Python replacement logic |
docker_base/Dockerfile |
docker_cuda/nvidia-cuda.Dockerfile |
NVIDIA driver libraries and CUDA toolkit integration | docker_cuda/nvidia-cuda.Dockerfile |
docker_core/Dockerfile |
Curated data-science packages (NumPy, pandas, etc.) as alternative heavy-weight base | docker_core/Dockerfile |
All images publish automatically to Docker Hub and Quay.io under the labnow namespace, supporting reproducible builds across development and production environments.
Summary
- Select the appropriate base image: Use
labnow/basefor CPU-only workloads,labnow/cudafor GPU acceleration, andlabnow/corefor pre-installed data-science stacks. - Configure network binding: Always set
c.ServerApp.ip = '0.0.0.0'(JupyterLab) orc.JupyterHub.bind_url(JupyterHub) to accept connections outside the container. - Expose correct ports: Port
8888for JupyterLab, port8000for JupyterHub. - Leverage existing Conda environment: The
docker_base/Dockerfileestablishes Python 3.12 via Miniconda, eliminating the need for manual Python installation in your extended images. - Enable GPU access: Append
--gpus alltodocker runcommands when usinglabnow/cuda-based images.
Frequently Asked Questions
Which LabNow base image should I choose for CPU versus GPU workloads?
Select labnow/base (built from docker_base/Dockerfile) for standard CPU-based data analysis and labnow/cuda (built from docker_cuda/nvidia-cuda.Dockerfile) when your notebooks require NVIDIA GPU acceleration. The CUDA image inherits all Conda and Python 3.12 capabilities from the base layer while adding proprietary driver support.
How do I configure authentication tokens and passwords in JupyterLab?
During image build, append c.ServerApp.token = 'YOUR_VALUE' to /root/.jupyter/jupyter_server_config.py as demonstrated in the single-user Dockerfile. For password-based authentication, replace the token line with c.ServerApp.password = 'argon2:...' using a hashed password generated via jupyter server password.
Can I extend LabNow images with additional Conda or pip packages?
Yes. Because the images use Conda as the primary Python provider, add RUN conda install -y package_name or RUN pip install package_name instructions to your application-layer Dockerfile. The uv installer included in docker_base/Dockerfile accelerates pip installations, while the isolated Conda environment prevents conflicts with system packages.
What is the difference between configuring JupyterLab on port 8888 versus JupyterHub on port 8000?
JupyterLab operates as a single-user server and traditionally listens on port 8888 with configuration keys prefixed by c.ServerApp. JupyterHub functions as a multi-user proxy and spawner, listening on port 8000 via c.JupyterHub.bind_url. The Hub spawns individual Lab instances for each user, whereas the standalone Lab image serves one user per container instance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →