Docker Development Setup for ERP-Unlocked Monorepo
This document provides comprehensive instructions for Docker-based development in the ERP-Unlocked monorepo, covering both containerized and hybrid development approaches.
Table of Contents
Section titled “Table of Contents”- Prerequisites
- Development Environment Setup
- Docker Compose Development
- Hybrid Development (Recommended)
- Building with Docker Bake
- Individual App Development
- Database Operations
- Troubleshooting
Prerequisites
Section titled “Prerequisites”Required Software
Section titled “Required Software”- Docker Desktop (4.0+)
- Node.js (
22.22.0+, matching.nvmrc) with pnpm (10+,10.33.4) - Python (3.11+) with uv (for Python packages)
- Git for version control
Install pnpm (if not already installed)
Section titled “Install pnpm (if not already installed)”corepack enablecorepack prepare pnpm@10.33.4 --activateVerify Installation
Section titled “Verify Installation”docker --versionnode --versionpnpm --versionpython --versionDevelopment Environment Setup
Section titled “Development Environment Setup”1. Clone and Setup Repository
Section titled “1. Clone and Setup Repository”git clone https://github.com/ERP-Unlocked/ordermatic.gitcd ordermatic
# Use pinned Node version (22.22.0)nvm use
# Install all dependencies using pnpm workspacespnpm install
# Install Python dependencies for root uv workspace# (members: packages/pdf-shared, apps/temporal-worker, packages/feature-flags-py, packages/erp-sql-py;# note: apps/dagster has its own separate uv.lock)uv sync2. Environment Configuration
Section titled “2. Environment Configuration”Create environment files for root shared infrastructure and the webapp:
# Root shared environment (Database, Redis, R2, Gemini, Temporal)cp .env.example .env
# Webapp environment (Clerk auth, public URLs)cp apps/webapp/.env.example apps/webapp/.env3. Configure Environment Variables
Section titled “3. Configure Environment Variables”Edit the environment files with your local configuration:
Root .env and apps/webapp/.env:
DATABASE_URL=postgresql://postgres:password@localhost:5432/erp_unlockedREDIS_URL=redis://localhost:6379CLERK_SECRET_KEY=your_clerk_secret_keyPUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_keyGEMINI_API_KEY=your_gemini_api_keyTEMPORAL_ADDRESS=localhost:7233Docker Compose Development
Section titled “Docker Compose Development”Starting All Services
Section titled “Starting All Services”# Start all services in backgrounddocker-compose up -d
# Start with logs visibledocker-compose upService-Specific Commands
Section titled “Service-Specific Commands”# Start only infrastructure services (PostgreSQL, Redis)docker-compose up -d postgres redis
# Start webapp and its dependenciesdocker-compose up webapp postgres redis
# Start PDF extraction (Temporal server + worker)docker-compose up temporal temporal-worker redis postgresManaging Services
Section titled “Managing Services”# View service statusdocker-compose ps
# View logs from all servicesdocker-compose logs -f
# View logs from specific servicedocker-compose logs -f webapp
# Stop all servicesdocker-compose down
# Stop and remove volumes (clean slate)docker-compose down -vHybrid Development (Recommended)
Section titled “Hybrid Development (Recommended)”For optimal development experience, run infrastructure in Docker but apps natively:
1. Start Infrastructure Services
Section titled “1. Start Infrastructure Services”# Start PostgreSQL, Redis, and Temporaldocker-compose up -d postgres redis temporal temporal-ui
# Verify services are runningdocker-compose ps2. Run Apps Natively
Section titled “2. Run Apps Natively”Terminal 1 - Webapp (Astro + React):
pnpm --filter webapp dev# → http://localhost:4321Terminal 2 - Temporal worker (PDF extraction and order automation):
set -a; . ./.env; set +auv run python apps/temporal-worker/worker.py3. Database Setup
Section titled “3. Database Setup”pnpm --filter @repo/db db:migratepnpm --filter @repo/db db:seed:billing # Optional: seed billing plansBuilding with Docker Bake
Section titled “Building with Docker Bake”Docker Bake provides unified build configuration for targets in docker-bake.hcl:
Build All Services
Section titled “Build All Services”# Build default targets (webapp, ts-temporal-worker)docker buildx bake
# Build and push to registry (for CI/CD)docker buildx bake --push
# Build with custom tagBRANCH_NAME=feature/my-feature COMMIT_SHA=abc123 docker buildx bakeBuild Specific Services
Section titled “Build Specific Services”# Build only webappdocker buildx bake webapp
# Build TypeScript Temporal workerdocker buildx bake ts-temporal-workerBuild Configuration
Section titled “Build Configuration”The docker-bake.hcl file defines build targets:
webapp/webapp-production: Astro customer applicationts-temporal-worker/ts-temporal-worker-production: TypeScript Temporal worker- Groups:
default(webapp,ts-temporal-worker),production(webapp-production,ts-temporal-worker-production),webapp
Individual App Development
Section titled “Individual App Development”Webapp (Astro + React)
Section titled “Webapp (Astro + React)”cd apps/webapp
# Development serverpnpm run dev # Start dev server on port 4321pnpm run build # Build for productionpnpm run preview # Preview production build
# Database operations (from repo root)pnpm --filter @repo/db db:migrate # Run database migrationspnpm --filter @repo/db db:studio # Open Drizzle Studio
# Testing and lintingpnpm run test # Run testspnpm run lint # Lint codepnpm turbo:typecheck # TypeScript type checking across workspaceDatabase Operations
Section titled “Database Operations”Using the Database Package (@repo/db)
Section titled “Using the Database Package (@repo/db)”# Schema operationspnpm --filter @repo/db db:generate # Generate migration from schema changespnpm --filter @repo/db db:migrate # Apply pending migrationspnpm --filter @repo/db db:push # Push schema directly (dev only)
# Development utilitiespnpm --filter @repo/db db:studio # Open Drizzle Studio (GUI)pnpm --filter @repo/db db:seed:billing # Seed billing plansDirect Database Access
Section titled “Direct Database Access”# Connect to PostgreSQL containerdocker exec -it erp_unlocked_postgres psql -U postgres -d erp_unlocked
# Common SQL operations\dt # List tables\d users # Describe table structureSELECT * FROM users LIMIT 5; # Query dataPackage Development
Section titled “Package Development”UI Components
Section titled “UI Components”cd packages/ui
# Developmentpnpm run dev # Storybook development serverpnpm run build # Build component librarypnpm run test # Test components
# Generate new componentpnpm run generate:component MyComponentShared Utils
Section titled “Shared Utils”cd packages/utils
# Development and testingpnpm run build # Build TypeScript utilitiespnpm run test # Run unit testspnpm run typecheck # TypeScript validationDevelopment Workflows
Section titled “Development Workflows”Full Stack Development
Section titled “Full Stack Development”- Start infrastructure:
docker-compose up -d postgres redis temporal temporal-ui - Run database migrations:
pnpm --filter @repo/db db:migrate - Start webapp:
pnpm --filter webapp dev - Start worker:
set -a; . ./.env; set +a; uv run python apps/temporal-worker/worker.py
Frontend-Only Development
Section titled “Frontend-Only Development”- Start infrastructure:
docker-compose up -d postgres redis - Run database migrations:
pnpm --filter @repo/db db:migrate - Start webapp:
pnpm --filter webapp dev
Extraction-Only Development
Section titled “Extraction-Only Development”- Start infrastructure:
docker-compose up -d postgres redis temporal - Start worker:
set -a; . ./.env; set +a; uv run python apps/temporal-worker/worker.py
Testing and Quality
Section titled “Testing and Quality”Running Tests
Section titled “Running Tests”# Run all JS/TS tests from rootpnpm test
# Run Python tests (packages/pdf-shared + apps/dagster)pnpm test:python
# Run Temporal worker Python testspnpm --filter @repo/temporal-worker testCode Quality
Section titled “Code Quality”# Lint all codepnpm lintpnpm lint:python
# Format all codepnpm formatpnpm format:python
# Type checkingpnpm turbo:typecheck
# Pre-commit hooks (automatic)git commit -m "Your changes" # Runs lint-staged and changeset verification automaticallyTroubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”Port Conflicts
Section titled “Port Conflicts”# Check what's using a portlsof -i :4321 # Check webapp portlsof -i :4322 # Check internal portal port
# Kill processes using portssudo kill -9 $(lsof -ti:4321)Database Connection Issues
Section titled “Database Connection Issues”# Verify PostgreSQL is runningdocker-compose ps postgres
# Check database connectivitydocker exec -it erp_unlocked_postgres pg_isready
# Reset database connectiondocker-compose restart postgrespnpm Workspace Issues
Section titled “pnpm Workspace Issues”# Clear pnpm store cache and reinstallpnpm store prunepnpm installDocker Build Issues
Section titled “Docker Build Issues”# Clean Docker cachedocker system prune -a
# Rebuild without cachedocker buildx bake --no-cache
# Check Docker Bake configurationdocker buildx bake --printDebug Commands
Section titled “Debug Commands”Service Health Checks
Section titled “Service Health Checks”# Check webapp healthcurl http://localhost:4321/api/health
# Check Redis connectivityredis-cli -h localhost -p 6379 ping
# Check PostgreSQL connectivitydocker exec erp_unlocked_postgres pg_isreadyService Logs
Section titled “Service Logs”# Application logsdocker-compose logs webappdocker-compose logs temporal-worker
# Database logsdocker-compose logs postgres
# Redis logsdocker-compose logs redisPerformance Optimization
Section titled “Performance Optimization”Development Performance
Section titled “Development Performance”# Use pnpm's node_modules linking for faster installspnpm config set store-dir ~/.pnpm-store
# Enable pnpm's shamefully-hoist for faster buildsecho "shamefully-hoist=true" >> .npmrc
# Use Docker BuildKit for faster buildsexport DOCKER_BUILDKIT=1Resource Management
Section titled “Resource Management”# Monitor Docker resource usagedocker stats
# Limit container resources in docker-compose.ymlservices: webapp: deploy: resources: limits: memory: 512M reservations: memory: 256MThis comprehensive setup ensures efficient development across the entire ERP-Unlocked monorepo, supporting both full containerized development and hybrid approaches based on your preferences and requirements.
Production Deployment Notes
Section titled “Production Deployment Notes”The production deployment process differs significantly from local development:
- PR-Based Workflow: All deployments use strict branch protection with conventional commit formats
- GitHub Actions: Automated builds triggered by pushes to protected branches (
main/staging) - Cloud Build:
gcp-deploy.ymltriggerscloudbuild.yaml, which builds, pushes, and deploys - Image Registry: Production images live in GCP Artifact Registry, tagged by commit SHA
- Two targets:
webapp/internalgo to Cloud Run;dagsterand both Temporal workers are systemd units on GCE VMs - Background jobs: Temporal workflows, not a separate job platform
For complete deployment procedures, see the Deployment Guide.