Docker Dev Setup
Run the complete Open Saasframe stack โ app, PostgreSQL, Redis, and Meilisearch โ inside Docker with hot reload. Every file change is picked up automatically. No local Node.js, Yarn, or native build tools are required.
This setup works on any OS. On Windows, it is slower than the native monorepo flow because bind-mounted file watching crosses the Windows/WSL filesystem boundary. Prefer the native path for day-to-day Windows development.
Prerequisitesโ
- Docker Desktop โ Windows ยท macOS ยท Linux
- Docker Compose v2+ (bundled with Docker Desktop)
- Git โ Windows ยท macOS:
xcode-select --installยท Linux:sudo apt install git - At least 4 GB RAM allocated to Docker (Docker Desktop โ Settings โ Resources)
- Enable the WSL 2 backend in Docker Desktop (Settings โ General โ "Use the WSL 2 based engine").
- Clone with CRLF handling disabled to avoid line-ending issues in shell scripts:
git config --global core.autocrlf input
Quick startโ
git clone https://github.com/saasframe/saasframe.git
cd saasframe
git checkout develop
# Optional: customise environment before first run
cp apps/saasframe/.env.example apps/saasframe/.env
# Build and start the full dev stack
docker compose -f docker-compose.fullapp.dev.yml up --build
The first run takes several minutes โ Docker builds the image, installs dependencies, builds packages, applies migrations, and seeds demo data. Subsequent starts are much faster because initialisation is cached in a named volume.
Once the runtime is ready, open:
- Splash / startup progress:
http://localhost:4000 - Backend:
http://localhost:3000/backend
Sign in with the default credentials printed during initialisation (typically admin@example.com / the password shown in the logs).
How it worksโ
The docker-compose.fullapp.dev.yml stack runs five services:
| Service | Image | Purpose |
|---|---|---|
| app | Built from Dockerfile (dev stage) | Next.js app with hot reload |
| postgres | pgvector/pgvector:pg17-trixie | PostgreSQL 17 with pgvector |
| redis | redis:7-alpine | Caching and event persistence |
| meilisearch | getmeili/meilisearch:v1.11 | Full-text search |
| opencode | Custom | Claude Code integration (optional) |
The app container:
- Mounts your source code from the host into
/app - Uses named volumes for
node_modules,.next, and packagedist/so the container manages its own builds - Enables file-watching via polling (
CHOKIDAR_USEPOLLING,WATCHPACK_POLLING) for reliable change detection on all platforms - On first run executes
yarn saasframe init; on subsequent runs applies pending migrations only
Common operationsโ
# Start in detached mode (background)
docker compose -f docker-compose.fullapp.dev.yml up -d
# View logs โ all services
docker compose -f docker-compose.fullapp.dev.yml logs -f
# View logs โ app only
docker compose -f docker-compose.fullapp.dev.yml logs -f app
# Rebuild after pulling new commits
docker compose -f docker-compose.fullapp.dev.yml up --build
# Stop all services
docker compose -f docker-compose.fullapp.dev.yml down
# Full reset โ deletes all data and cached builds
docker compose -f docker-compose.fullapp.dev.yml down -v
docker compose -f docker-compose.fullapp.dev.yml up --build
Docker wrapper commandsโ
The repository exposes yarn docker:* commands that run the equivalent workflow inside the running app container โ so you don't need to type docker compose exec ... manually.
Start the dev stack first:
yarn docker:dev:up
Then run monorepo workflows from the host:
yarn docker:build:packages
yarn docker:generate
yarn docker:initialize
yarn docker:initialize -- --reinstall
yarn docker:db:migrate
yarn docker:lint
yarn docker:typecheck
yarn docker:test
Restart the app service and tail logs:
yarn docker:dev
# Skip the install/build/generate phase (faster restart):
yarn docker:dev -- --skip-rebuilt
Environment variablesโ
All variables are pre-configured with sensible defaults in the compose file. Override them in apps/saasframe/.env before starting.
| Variable | Default | Description |
|---|---|---|
APP_PORT | 3000 | Host port for the app |
SF_DEV_SPLASH_PORT | 4000 | Host port for the startup splash page |
SF_DEV_AUTO_OPEN | 1 | Set to 0 to disable browser auto-open |
POSTGRES_PASSWORD | postgres | Database password |
JWT_SECRET | JWT | Auth token secret โ change for production |
OPENAI_API_KEY | โ | Enables OpenAI-backed AI features; combine it with SF_DISABLE_VECTOR_SEARCH_AUTOINDEXING=false to turn vector auto-indexing on |
SF_DISABLE_VECTOR_SEARCH_AUTOINDEXING | true in the shipped example env | Set to false or remove it to enable automatic vector indexing |
DEMO_MODE | true | Seeds demo CRM data on first run |
Vector auto-indexing is disabled by default in apps/saasframe/.env.example. To enable it, configure an embedding provider such as OPENAI_API_KEY and set SF_DISABLE_VECTOR_SEARCH_AUTOINDEXING=false before you start the stack. The legacy alias DISABLE_VECTOR_SEARCH_AUTOINDEXING=1 is still honored for older deployments.
Troubleshootingโ
Container fails to start on Windows:
- Ensure WSL 2 backend is enabled in Docker Desktop.
- Verify the repo was cloned with
core.autocrlf=inputto avoid CRLF issues in shell scripts. - Allocate at least 4 GB RAM to Docker (Docker Desktop โ Settings โ Resources).
File changes not detected: The compose file sets polling by default. If changes are still not picked up:
docker compose -f docker-compose.fullapp.dev.yml restart app
Port conflicts:
# Change app port
APP_PORT=3001 docker compose -f docker-compose.fullapp.dev.yml up
# Change splash port
SF_DEV_SPLASH_PORT=4100 docker compose -f docker-compose.fullapp.dev.yml up
# Change Postgres port (when localhost:5432 is occupied)
POSTGRES_PORT=55432 docker compose -f docker-compose.fullapp.dev.yml up
# And update DATABASE_URL in .env to match
Slow file watching on Windows/WSL 2:
Store the repository inside the WSL 2 filesystem (\\wsl$\Ubuntu\home\...) rather than on the Windows filesystem (/mnt/c/...) for significantly better I/O performance.