This monorepo hosts the FastAPI backend (apps/api) and the Vite-powered React frontend (apps/web). You can still run each workspace directly with uv or npm, but a Docker Compose stack now provides a single command that boots both services plus PostgreSQL with the same settings used by the native scripts.
- Docker Engine 24+ (Docker Desktop works on macOS/Windows) with the Compose v2 plugin.
- 8 GB RAM available for containers (API + web + Postgres barely use ~1 GB but leave headroom for tooling).
- Optional: Python 3.12 +
uvand Node 18+ if you prefer to run the workspaces outside Docker (seeapps/api/README.mdandapps/web/README.md).
# Build images (picks up the Dockerfiles in apps/api and apps/web) and start the stack
docker compose up --buildCompose mounts the repo into each container for live reload (FastAPI auto-reload + Vite HMR) and keeps dependency caches in named volumes:
| Volume | Mount | Purpose |
|---|---|---|
api-venv |
/workspace/apps/api/.venv |
Reuses uv sync installs |
api-uv-cache |
/root/.cache/uv |
Keeps wheel/cache data |
web-node-modules |
/workspace/apps/web/node_modules |
Keeps npm installs outside the bind mount |
postgres-data |
/var/lib/postgresql/data |
Persists database state |
.env.compose(checked in) stores the defaults for database credentials, API CORS settings, and front-end env vars that containers need.- Optional
.env.compose.local(ignored) lets you change container-level settings. Copy the default file, tweak values, then point Compose at it by exportingCOMPOSE_ENV_FILE=.env.compose.localor writing the variable into your root.env. - Optional root
.env(ignored) feeds host-level overrides such as customAPI_PORT,WEB_PORT, or a differentCOMPOSE_ENV_FILE. Example:
echo "API_PORT=9000" >> .env
echo "COMPOSE_ENV_FILE=.env.compose.local" >> .env
docker compose up --buildWithout any overrides the services bind to http://localhost:8000 (API), http://localhost:5173 (web), and localhost:5432 (Postgres).
postgres-1 | PostgreSQL init process complete; ready for start up.
postgres-1 | database system is ready to accept connections
api-1 | ✔ Synced virtual environment using uv.lock
api-1 | INFO: Will watch for changes in these directories: ['/workspace/apps/api']
api-1 | INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
web-1 | VITE v7.1.7 ready in 1506 ms
web-1 | ➜ Local: http://0.0.0.0:5173/
web-1 | ➜ Network: http://127.0.0.1:5173/
web-1 | ready in 30 ms. Waiting for file changes...
Save files under apps/api or apps/web and the containers will reload automatically without rebuilding images.
| Purpose | Command |
|---|---|
| Apply DB migrations | docker compose exec api uv run alembic upgrade head |
| Generate a migration | docker compose exec api uv run alembic revision --autogenerate -m "add table" |
| Run backend tests | docker compose exec api uv run pytest |
| Run frontend tests | docker compose exec web npm run test |
| Inspect Postgres | docker compose exec postgres psql -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-second_brain} |
| Tail logs | docker compose logs -f api (or web, postgres) |
| Stop stack | docker compose down |
| Reset volumes/data | docker compose down -v |
The API container reads the same DATABASE_* variables as Alembic, so migrations work exactly like the native workflow. After the stack is up, run:
docker compose exec api uv run alembic upgrade headSample output:
api-1 | INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
api-1 | INFO [alembic.runtime.migration] Running upgrade -> 1f6b95cf29d9, create bookmark tables
Use docker compose exec postgres psql -U postgres -d second_brain -c '\dt' to confirm tables or inspect data.
If you would rather run the workspaces directly:
cd apps/api && uv sync && uv run uvicorn app.main:app --reload
cd apps/web && npm install && npm run devThose commands match the ones used inside the Compose stack, so instructions in the per-app READMEs remain accurate.
- Environment edits not taking effect – double-check whether the value lives in
.env(host-level override) or.env.compose(container-level). Remember to restart the stack after editing. - Dependency issues – wipe the cache volumes (
docker compose down -v api-venv api-uv-cache web-node-modules) or rundocker compose down -vto rebuild everything. - Port already in use – override
API_PORT/WEB_PORT/POSTGRES_PORTin your root.envand restart the stack. - Need a shell inside a service –
docker compose exec api bash(orweb,postgres) drops you into the container so you can runuv,npm, orpsqlcommands interactively.