771 lines
18 KiB
Markdown
771 lines
18 KiB
Markdown
# DreamChat Deployment Guide
|
|
|
|
## Overview
|
|
|
|
This document covers the deployment configuration including Docker Compose setup, DevContainer configuration, and production deployment procedures.
|
|
|
|
## DevContainer Setup
|
|
|
|
### .devcontainer/devcontainer.json
|
|
|
|
```json
|
|
{
|
|
"name": "DreamChat Development",
|
|
"dockerComposeFile": "docker-compose.yml",
|
|
"service": "app",
|
|
"workspaceFolder": "/workspace",
|
|
"features": {
|
|
"ghcr.io/devcontainers/features/node:1": {
|
|
"version": "20"
|
|
},
|
|
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
|
|
},
|
|
"customizations": {
|
|
"vscode": {
|
|
"extensions": [
|
|
"dbaeumer.vscode-eslint",
|
|
"esbenp.prettier-vscode",
|
|
"bradlc.vscode-tailwindcss",
|
|
"ms-vscode.vscode-typescript-next",
|
|
"nestjs.vscode-nestjs",
|
|
"prisma.prisma"
|
|
],
|
|
"settings": {
|
|
"editor.formatOnSave": true,
|
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
"typescript.preferences.importModuleSpecifier": "relative"
|
|
}
|
|
}
|
|
},
|
|
"forwardPorts": [3000, 5173, 5432, 8080],
|
|
"portsAttributes": {
|
|
"3000": {
|
|
"label": "Backend API",
|
|
"onAutoForward": "notify"
|
|
},
|
|
"5173": {
|
|
"label": "Frontend Dev Server",
|
|
"onAutoForward": "notify"
|
|
},
|
|
"5432": {
|
|
"label": "PostgreSQL",
|
|
"onAutoForward": "silent"
|
|
},
|
|
"8080": {
|
|
"label": "Keycloak",
|
|
"onAutoForward": "notify"
|
|
}
|
|
},
|
|
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
|
"remoteUser": "node",
|
|
"mounts": [
|
|
"source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume",
|
|
"source=${localWorkspaceFolderBasename}-pnpm-store,target=/home/node/.local/share/pnpm/store,type=volume"
|
|
]
|
|
}
|
|
```
|
|
|
|
### .devcontainer/docker-compose.yml
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
app:
|
|
build:
|
|
context: ..
|
|
dockerfile: .devcontainer/Dockerfile
|
|
volumes:
|
|
- ..:/workspace:cached
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
command: sleep infinity
|
|
environment:
|
|
- DATABASE_URL=postgresql://postgres:postgres@db:5432/dreamchat
|
|
- REDIS_URL=redis://redis:6379
|
|
- KEYCLOAK_URL=http://keycloak:8080
|
|
depends_on:
|
|
- db
|
|
- redis
|
|
- keycloak
|
|
networks:
|
|
- dreamchat-network
|
|
|
|
db:
|
|
image: ankane/pgvector:latest
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: postgres
|
|
POSTGRES_DB: dreamchat
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
ports:
|
|
- "5432:5432"
|
|
networks:
|
|
- dreamchat-network
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
restart: unless-stopped
|
|
ports:
|
|
- "6379:6379"
|
|
networks:
|
|
- dreamchat-network
|
|
|
|
volumes:
|
|
postgres-data:
|
|
|
|
networks:
|
|
dreamchat-network:
|
|
driver: bridge
|
|
```
|
|
|
|
**Note:** Keycloak is configured as an external service. Set `KEYCLOAK_URL` in your environment to point to your external Keycloak instance.
|
|
|
|
### .devcontainer/Dockerfile
|
|
|
|
```dockerfile
|
|
FROM mcr.microsoft.com/devcontainers/typescript-node:20
|
|
|
|
# Install additional tools
|
|
RUN apt-get update && apt-get install -y \
|
|
postgresql-client \
|
|
redis-tools \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Install pnpm
|
|
RUN npm install -g pnpm@8
|
|
|
|
# Set working directory
|
|
WORKDIR /workspace
|
|
|
|
# Install global packages
|
|
RUN npm install -g @nestjs/cli@latest
|
|
|
|
# Create non-root user
|
|
USER node
|
|
```
|
|
|
|
### .devcontainer/post-create.sh
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
echo "🚀 Setting up DreamChat monorepo development environment..."
|
|
|
|
# Install pnpm globally
|
|
npm install -g pnpm@8
|
|
|
|
# Install all dependencies (uses pnpm workspaces)
|
|
echo "📦 Installing dependencies..."
|
|
cd /workspace
|
|
pnpm install
|
|
|
|
# Build shared packages first
|
|
echo "📦 Building shared packages..."
|
|
pnpm --filter @dreamchat/shared build
|
|
|
|
# Generate Prisma client
|
|
pnpm db:generate
|
|
|
|
# Copy environment files if they don't exist
|
|
if [ ! -f /workspace/apps/backend/.env ]; then
|
|
echo "⚙️ Creating backend .env file..."
|
|
cat > /workspace/apps/backend/.env << EOF
|
|
NODE_ENV=development
|
|
PORT=3000
|
|
DATABASE_URL=postgresql://postgres:postgres@db:5432/dreamchat
|
|
JWT_SECRET=dev-jwt-secret-change-in-production
|
|
JWT_EXPIRES_IN=1h
|
|
JWT_REFRESH_EXPIRES_IN=7d
|
|
LLM_PROVIDER=openrouter
|
|
LLM_API_KEY=your-openrouter-api-key
|
|
LLM_MODEL=openai/gpt-4o
|
|
KEYCLOAK_URL=http://localhost:8080
|
|
KEYCLOAK_REALM=dreamchat
|
|
KEYCLOAK_CLIENT_ID=dreamchat-backend
|
|
EOF
|
|
fi
|
|
|
|
if [ ! -f /workspace/apps/frontend/.env ]; then
|
|
echo "⚙️ Creating frontend .env file..."
|
|
cat > /workspace/apps/frontend/.env << EOF
|
|
VITE_API_URL=http://localhost:3000/api
|
|
VITE_WS_URL=ws://localhost:3000
|
|
VITE_KEYCLOAK_URL=http://localhost:8080
|
|
VITE_KEYCLOAK_REALM=dreamchat
|
|
VITE_KEYCLOAK_CLIENT_ID=dreamchat-frontend
|
|
EOF
|
|
fi
|
|
|
|
echo "✅ Development environment setup complete!"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Start all apps: pnpm dev"
|
|
echo "2. Or start individually:"
|
|
echo " - Backend: pnpm --filter @dreamchat/backend dev"
|
|
echo " - Frontend: pnpm --filter @dreamchat/frontend dev"
|
|
echo "3. Access Keycloak admin at http://localhost:8080 (admin/admin)"
|
|
```
|
|
|
|
## Docker Compose Production
|
|
|
|
### docker-compose.yml (Root)
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
# Backend API
|
|
backend:
|
|
build:
|
|
context: .
|
|
dockerfile: apps/backend/Dockerfile
|
|
restart: unless-stopped
|
|
environment:
|
|
- NODE_ENV=production
|
|
- PORT=3000
|
|
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@db:5432/dreamchat
|
|
- JWT_SECRET=${JWT_SECRET}
|
|
- JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-1h}
|
|
- JWT_REFRESH_EXPIRES_IN=${JWT_REFRESH_EXPIRES_IN:-7d}
|
|
- LLM_PROVIDER=${LLM_PROVIDER}
|
|
- LLM_API_KEY=${LLM_API_KEY}
|
|
- LLM_MODEL=${LLM_MODEL}
|
|
- EMBEDDING_PROVIDER=${EMBEDDING_PROVIDER:-local}
|
|
- EMBEDDING_MODEL=${EMBEDDING_MODEL:-Xenova/all-MiniLM-L6-v2}
|
|
- EMBEDDING_DIMENSION=${EMBEDDING_DIMENSION:-384}
|
|
- EMBEDDING_DEVICE=${EMBEDDING_DEVICE:-cpu}
|
|
- HUGGINGFACE_API_KEY=${HUGGINGFACE_API_KEY}
|
|
- KEYCLOAK_URL=${KEYCLOAK_URL}
|
|
- KEYCLOAK_REALM=${KEYCLOAK_REALM}
|
|
- KEYCLOAK_CLIENT_ID=${KEYCLOAK_CLIENT_ID}
|
|
- KEYCLOAK_CLIENT_SECRET=${KEYCLOAK_CLIENT_SECRET}
|
|
ports:
|
|
- "3000:3000"
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
volumes:
|
|
- backend-logs:/app/logs
|
|
- model-cache:/app/models
|
|
networks:
|
|
- dreamchat-network
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
|
|
# Frontend (static file server)
|
|
# Note: External reverse proxy expected for SSL and routing
|
|
frontend:
|
|
build:
|
|
context: .
|
|
dockerfile: apps/frontend/Dockerfile
|
|
restart: unless-stopped
|
|
ports:
|
|
- "3001:3000"
|
|
environment:
|
|
- VITE_API_URL=/api
|
|
- VITE_WS_URL=/ws
|
|
depends_on:
|
|
- backend
|
|
networks:
|
|
- dreamchat-network
|
|
|
|
# Database
|
|
db:
|
|
image: ankane/pgvector:latest
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
POSTGRES_DB: dreamchat
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
- ./init-scripts:/docker-entrypoint-initdb.d
|
|
networks:
|
|
- dreamchat-network
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
# Redis (optional, for session storage and caching)
|
|
redis:
|
|
image: redis:7-alpine
|
|
restart: unless-stopped
|
|
volumes:
|
|
- redis-data:/data
|
|
networks:
|
|
- dreamchat-network
|
|
|
|
volumes:
|
|
postgres-data:
|
|
redis-data:
|
|
backend-logs:
|
|
model-cache: # Persist downloaded embedding models
|
|
|
|
networks:
|
|
dreamchat-network:
|
|
driver: bridge
|
|
```
|
|
|
|
### Embedding Model Cache (Optional)
|
|
|
|
To avoid re-downloading models on every restart, models are cached in a Docker volume:
|
|
|
|
```yaml
|
|
# Add to docker-compose volumes
|
|
volumes:
|
|
model-cache:
|
|
```
|
|
|
|
Models are downloaded on first use and cached at `/app/models` in the backend container.
|
|
|
|
Common models and their sizes:
|
|
- `Xenova/all-MiniLM-L6-v2`: ~80MB (384 dimensions)
|
|
- `Xenova/all-mpnet-base-v2`: ~420MB (768 dimensions)
|
|
- `BAAI/bge-small-en`: ~130MB (384 dimensions)
|
|
|
|
### .env.example
|
|
|
|
```bash
|
|
# Database
|
|
POSTGRES_PASSWORD=your_secure_password_here
|
|
|
|
# JWT
|
|
JWT_SECRET=your_jwt_secret_key_min_32_chars
|
|
JWT_EXPIRES_IN=1h
|
|
JWT_REFRESH_EXPIRES_IN=7d
|
|
|
|
# LLM Configuration
|
|
LLM_PROVIDER=openrouter
|
|
LLM_API_KEY=sk-or-v1-...
|
|
LLM_MODEL=openai/gpt-4o
|
|
|
|
# Embedding Configuration (Local HuggingFace by default)
|
|
EMBEDDING_PROVIDER=local
|
|
EMBEDDING_MODEL=Xenova/all-MiniLM-L6-v2
|
|
EMBEDDING_DIMENSION=384
|
|
EMBEDDING_DEVICE=cpu
|
|
|
|
# HuggingFace API (optional - if not using local embeddings)
|
|
# HUGGINGFACE_API_KEY=hf_...
|
|
|
|
# Keycloak (optional - for external auth)
|
|
KEYCLOAK_URL=http://keycloak:8080
|
|
KEYCLOAK_REALM=dreamchat
|
|
KEYCLOAK_CLIENT_ID=dreamchat-backend
|
|
KEYCLOAK_CLIENT_SECRET=your_keycloak_secret
|
|
```
|
|
|
|
## Backend Dockerfile
|
|
|
|
```dockerfile
|
|
# apps/backend/Dockerfile
|
|
FROM node:24-alpine AS base
|
|
RUN npm install -g pnpm@8
|
|
|
|
FROM base AS dependencies
|
|
WORKDIR /app
|
|
|
|
# Copy workspace configuration
|
|
COPY pnpm-workspace.yaml package.json ./
|
|
COPY apps/backend/package.json ./apps/backend/
|
|
COPY packages/shared/package.json ./packages/shared/
|
|
|
|
# Install dependencies
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
COPY --from=dependencies /app/node_modules ./node_modules
|
|
COPY --from=dependencies /app/apps/backend/node_modules ./apps/backend/node_modules
|
|
COPY --from=dependencies /app/packages/shared/node_modules ./packages/shared/node_modules
|
|
|
|
# Copy source code
|
|
COPY packages/shared ./packages/shared
|
|
COPY apps/backend ./apps/backend
|
|
|
|
# Build shared packages first
|
|
RUN pnpm --filter @dreamchat/shared build
|
|
|
|
# Build backend
|
|
RUN pnpm --filter @dreamchat/backend build
|
|
|
|
FROM base AS production
|
|
WORKDIR /app
|
|
|
|
# Copy only production dependencies
|
|
COPY --from=dependencies /app/node_modules ./node_modules
|
|
COPY --from=dependencies /app/apps/backend/node_modules ./apps/backend/node_modules
|
|
COPY --from=build /app/apps/backend/dist ./dist
|
|
COPY --from=build /app/packages/shared/dist ./node_modules/@dreamchat/shared/dist
|
|
|
|
# Create logs directory
|
|
RUN mkdir -p /app/logs
|
|
|
|
# Non-root user
|
|
RUN addgroup -g 1001 -S nodejs
|
|
RUN adduser -S nodejs -u 1001
|
|
USER nodejs
|
|
|
|
EXPOSE 3000
|
|
|
|
CMD ["node", "dist/main.js"]
|
|
```
|
|
|
|
## Frontend Dockerfile
|
|
|
|
```dockerfile
|
|
# apps/frontend/Dockerfile
|
|
FROM node:24-alpine AS base
|
|
RUN npm install -g pnpm@8
|
|
|
|
FROM base AS dependencies
|
|
WORKDIR /app
|
|
|
|
# Copy workspace configuration
|
|
COPY pnpm-workspace.yaml package.json ./
|
|
COPY apps/frontend/package.json ./apps/frontend/
|
|
COPY packages/shared/package.json ./packages/shared/
|
|
|
|
# Install dependencies
|
|
RUN pnpm install --frozen-lockfile
|
|
|
|
FROM base AS build
|
|
WORKDIR /app
|
|
COPY --from=dependencies /app/node_modules ./node_modules
|
|
COPY --from=dependencies /app/apps/frontend/node_modules ./apps/frontend/node_modules
|
|
COPY --from=dependencies /app/packages/shared/node_modules ./packages/shared/node_modules
|
|
|
|
# Copy source code
|
|
COPY packages/shared ./packages/shared
|
|
COPY apps/frontend ./apps/frontend
|
|
|
|
# Build shared packages first
|
|
RUN pnpm --filter @dreamchat/shared build
|
|
|
|
# Build frontend
|
|
RUN pnpm --filter @dreamchat/frontend build
|
|
|
|
# Production stage - using serve for static files
|
|
# External reverse proxy (nginx/traefik/etc.) expected
|
|
FROM node:24-alpine AS production
|
|
WORKDIR /app
|
|
|
|
# Install serve
|
|
RUN npm install -g serve
|
|
|
|
# Copy built assets
|
|
COPY --from=build /app/apps/frontend/dist ./dist
|
|
|
|
# Create non-root user
|
|
RUN addgroup -g 1001 -S nodejs
|
|
RUN adduser -S nodejs -u 1001
|
|
USER nodejs
|
|
|
|
EXPOSE 3000
|
|
|
|
# Serve static files
|
|
# Note: External reverse proxy should handle:
|
|
# - SSL/TLS termination
|
|
# - Path routing (/api -> backend, / -> frontend)
|
|
# - WebSocket proxying
|
|
CMD ["serve", "-s", "dist", "-l", "3000"]
|
|
```
|
|
|
|
### External Reverse Proxy Configuration
|
|
|
|
The frontend container serves static files on port 3000. An external reverse proxy is expected to handle:
|
|
|
|
- **SSL/TLS termination**
|
|
- **Path routing**:
|
|
- `/api/*` → Backend (port 3000)
|
|
- `/ws` → Backend WebSocket (port 3000)
|
|
- `/*` → Frontend (port 3001)
|
|
- **Static file caching**
|
|
|
|
Example nginx configuration:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name dreamchat.example.com;
|
|
|
|
ssl_certificate /path/to/cert.pem;
|
|
ssl_certificate_key /path/to/key.pem;
|
|
|
|
# API proxy
|
|
location /api {
|
|
proxy_pass http://backend:3000/api;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
|
|
# WebSocket proxy
|
|
location /ws {
|
|
proxy_pass http://backend:3000;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
|
|
# Frontend static files
|
|
location / {
|
|
proxy_pass http://frontend:3000;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Keycloak Configuration (External)
|
|
|
|
Keycloak is configured as an external service with support for group/role/attribute-based authorization and auto-user creation.
|
|
|
|
### Prerequisites
|
|
|
|
1. Have a running Keycloak instance (self-hosted or managed)
|
|
2. Configure the following environment variables in `.env`:
|
|
|
|
```bash
|
|
# Basic Keycloak settings
|
|
KEYCLOAK_ENABLED=true
|
|
KEYCLOAK_URL=http://your-keycloak-server:8080
|
|
KEYCLOAK_REALM=dreamchat
|
|
KEYCLOAK_CLIENT_ID=dreamchat-backend
|
|
KEYCLOAK_CLIENT_SECRET=your_keycloak_secret
|
|
|
|
# Authorization settings (optional but recommended)
|
|
KEYCLOAK_REQUIRED_GROUP=dreamchat-users
|
|
KEYCLOAK_REQUIRED_ROLE=dreamchat-access
|
|
KEYCLOAK_REQUIRED_CLIENT_ROLE=user
|
|
KEYCLOAK_REQUIRED_ATTRIBUTE=approved:true
|
|
|
|
# Auto-create users
|
|
KEYCLOAK_AUTO_CREATE_USER=true
|
|
KEYCLOAK_DEFAULT_USER_ROLE=USER
|
|
```
|
|
|
|
### Keycloak Realm Setup
|
|
|
|
1. Access your Keycloak admin console
|
|
2. Create new realm: `dreamchat`
|
|
3. Create client: `dreamchat-backend`
|
|
- Client authentication: ON
|
|
- Authorization: ON
|
|
- Valid redirect URIs: `http://localhost:3000/*`
|
|
- Web origins: `http://localhost:3000`
|
|
|
|
4. Create client: `dreamchat-frontend`
|
|
- Client authentication: OFF
|
|
- Valid redirect URIs: `http://localhost:5173/*`
|
|
- Web origins: `http://localhost:5173`
|
|
|
|
### Authorization Configuration
|
|
|
|
You can restrict access based on:
|
|
|
|
**1. Group Membership**
|
|
```bash
|
|
KEYCLOAK_REQUIRED_GROUP=dreamchat-users
|
|
```
|
|
Users must be members of this Keycloak group to access the application.
|
|
|
|
**2. Realm Role**
|
|
```bash
|
|
KEYCLOAK_REQUIRED_ROLE=dreamchat-access
|
|
```
|
|
Users must have this realm-level role.
|
|
|
|
**3. Client Role**
|
|
```bash
|
|
KEYCLOAK_REQUIRED_CLIENT_ROLE=user
|
|
```
|
|
Users must have this role for the `dreamchat-backend` client.
|
|
|
|
**4. User Attribute**
|
|
```bash
|
|
KEYCLOAK_REQUIRED_ATTRIBUTE=department:engineering
|
|
# or
|
|
KEYCLOAK_REQUIRED_ATTRIBUTE=approved:true
|
|
```
|
|
Users must have this attribute with the specified value.
|
|
|
|
### User Auto-Creation
|
|
|
|
When `KEYCLOAK_AUTO_CREATE_USER=true`:
|
|
- Users are automatically created in the database on first Keycloak login
|
|
- Username is derived from Keycloak preferred_username
|
|
- Email is taken from Keycloak email claim
|
|
- Role is set to `KEYCLOAK_DEFAULT_USER_ROLE` (default: USER)
|
|
- The `keycloakSub` field links the local user to Keycloak
|
|
|
|
When `KEYCLOAK_AUTO_CREATE_USER=false`:
|
|
- Only existing local users can log in via Keycloak
|
|
- The `keycloakSub` must match between Keycloak and local user
|
|
|
|
### Example Keycloak Group/Role Setup
|
|
|
|
1. Create a group: `dreamchat-users`
|
|
2. Create a realm role: `dreamchat-access`
|
|
3. Assign the group and/or role to users who should have access
|
|
4. Configure `KEYCLOAK_REQUIRED_GROUP` and/or `KEYCLOAK_REQUIRED_ROLE`
|
|
|
|
### realm-export.json (Optional)
|
|
|
|
```json
|
|
{
|
|
"realm": "dreamchat",
|
|
"enabled": true,
|
|
"clients": [
|
|
{
|
|
"clientId": "dreamchat-backend",
|
|
"enabled": true,
|
|
"clientAuthenticatorType": "client-secret",
|
|
"secret": "**********",
|
|
"redirectUris": ["http://localhost:3000/*"],
|
|
"webOrigins": ["http://localhost:3000"],
|
|
"protocol": "openid-connect"
|
|
},
|
|
{
|
|
"clientId": "dreamchat-frontend",
|
|
"enabled": true,
|
|
"publicClient": true,
|
|
"redirectUris": ["http://localhost:5173/*"],
|
|
"webOrigins": ["http://localhost:5173"],
|
|
"protocol": "openid-connect"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Deployment Procedures
|
|
|
|
### Local Development
|
|
|
|
```bash
|
|
# Using DevContainer
|
|
1. Open project in VS Code
|
|
2. Click "Reopen in Container"
|
|
3. Wait for setup to complete
|
|
4. Start services:
|
|
- Terminal 1: pnpm --filter @dreamchat/backend dev
|
|
- Terminal 2: pnpm --filter @dreamchat/frontend dev
|
|
- Or run all: pnpm dev
|
|
```
|
|
|
|
### Production Deployment
|
|
|
|
```bash
|
|
# 1. Clone repository
|
|
git clone https://github.com/yourusername/dreamchat.git
|
|
cd dreamchat
|
|
|
|
# 2. Create environment file
|
|
cp .env.example .env
|
|
# Edit .env with production values
|
|
|
|
# 3. Build and start
|
|
docker-compose up -d --build
|
|
|
|
# 4. Run database migrations
|
|
docker-compose exec backend pnpm db:migrate
|
|
|
|
# 5. Check health
|
|
curl http://localhost:3000/health
|
|
|
|
# 6. View logs
|
|
docker-compose logs -f backend
|
|
```
|
|
|
|
### Backup and Restore
|
|
|
|
```bash
|
|
# Backup database
|
|
docker-compose exec db pg_dump -U postgres -Fc dreamchat > backup_$(date +%Y%m%d).dump
|
|
|
|
# Restore database
|
|
docker-compose exec -T db pg_restore -U postgres -d dreamchat < backup_20240223.dump
|
|
|
|
# Backup volumes
|
|
docker run --rm -v dreamchat_postgres-data:/data -v $(pwd):/backup alpine tar czf /backup/postgres-backup.tar.gz -C /data .
|
|
```
|
|
|
|
### Updates
|
|
|
|
```bash
|
|
# Pull latest changes
|
|
git pull origin main
|
|
|
|
# Rebuild and restart
|
|
docker-compose down
|
|
docker-compose up -d --build
|
|
|
|
# Run migrations
|
|
docker-compose exec backend npx prisma migrate deploy
|
|
```
|
|
|
|
## Monitoring and Logging
|
|
|
|
### Health Checks
|
|
|
|
```bash
|
|
# Backend health
|
|
curl http://localhost:3000/health
|
|
|
|
# Database health
|
|
docker-compose exec db pg_isready -U postgres
|
|
|
|
# Full stack
|
|
docker-compose ps
|
|
```
|
|
|
|
### Log Management
|
|
|
|
```bash
|
|
# View all logs
|
|
docker-compose logs
|
|
|
|
# View specific service
|
|
docker-compose logs -f backend
|
|
|
|
# View last 100 lines
|
|
docker-compose logs --tail=100 backend
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Change default passwords** in production
|
|
2. **Use HTTPS** with valid SSL certificates
|
|
3. **Enable firewall** rules for required ports only
|
|
4. **Regular updates** of base images and dependencies
|
|
5. **Secrets management** - use Docker secrets or external vault
|
|
6. **Network isolation** - separate networks for different services
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Database connection failed**
|
|
- Check DATABASE_URL environment variable
|
|
- Ensure db service is healthy: `docker-compose ps`
|
|
|
|
2. **WebSocket not connecting**
|
|
- Verify VITE_WS_URL matches your domain
|
|
- Check Nginx proxy configuration
|
|
|
|
3. **Keycloak authentication issues**
|
|
- Verify client configuration in Keycloak admin
|
|
- Check redirect URIs match exactly
|
|
|
|
4. **File upload fails**
|
|
- Check file size limits in Nginx config
|
|
- Verify disk space in backend container
|