Spinning up Jupyter with Docker, Postgres, and uv

Needed a local Jupyter setup with vector search capabilities. Here’s how I got Docker, Postgres with pgvector, and uv working together.

  1. Initialize the the project with uv and desired python version. Add jupyterlab and any other packages that you need.
uv init --python 3.13 # required python version. it will add .python-version file
uv add jupyterlab psycopg pgvector
uv lock # freeze dependencies for docker
  1. The docker-compose file

name: jupyter-postgres-with-uv

services:
	postgres:
		image: pgvector/pgvector:0.8.1-pg17-trixie
		container_name: pgvector-db
		environment:
			POSTGRES_USER: <DB_USERNAME>
			POSTGRES_PASSWORD: <DB_PASSWORD>
			POSTGRES_DB: <DB_NAME>
		ports:
			- "5432:5432"
		volumes:
			- pgdata:/var/lib/postgresql/data


adminer:
	image: adminer # light weight php file to manage postgresql
	container_name: adminer-ui
	restart: always
	ports:
		- "8080:8080"
	depends_on:
		- postgres



jupyter:
	build: .
	container_name: jupyter-dev
	volumes:
		- ./notebooks:/app/notebooks
	ports:
		- "8888:8888"
	depends_on:
		- postgres


volumes:
	pgdata:
  1. Dockerfile
FROM python:3.13-slim-bookworm

ENV APP_HOME=/app
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME


# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# System dependencies
RUN apt-get update && apt-get install -y \
	build-essential \
	libpq-dev \
	git \
	curl \
	&& rm -rf /var/lib/apt/lists/*


RUN pip install --no-cache-dir uv

# Copy requirements
COPY pyproject.toml uv.lock ./

# Install deps via uv
RUN uv sync --frozen --all-groups


ENV VIRTUAL_ENV=$APP_HOME/.venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

# Expose Jupyter port
EXPOSE 8888

# Run Jupyter (no token, no password for local dev, not suitable for deploying)

CMD ["python", "-m", "jupyterlab", "--ip=0.0.0.0", "--allow-root", "--no-browser", "--NotebookApp.token=", "--NotebookApp.password="]
  1. Build and run the containers in detached mode:
docker compose up -d --build

That’s it!

Important: Virtual Environment Path

UV creates a virtual environment in ./.venv at the root of your project. The Dockerfile sets this path so Jupyter runs from the correct environment:

ENV VIRTUAL_ENV=$APP_HOME/.venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

Without this, you’ll get an error like /usr/local/bin/python: No module named jupyterlab because Docker will try to use the system Python instead of the one with your packages.