feat: add implementation plan and monorepo guide for DreamChat project
This commit is contained in:
725
doc/deployment.md
Normal file
725
doc/deployment.md
Normal file
@@ -0,0 +1,725 @@
|
||||
# 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
|
||||
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:23.0
|
||||
restart: unless-stopped
|
||||
command: start-dev
|
||||
environment:
|
||||
KEYCLOAK_ADMIN: admin
|
||||
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||
KC_DB: postgres
|
||||
KC_DB_URL: jdbc:postgresql://db:5432/keycloak
|
||||
KC_DB_USERNAME: postgres
|
||||
KC_DB_PASSWORD: postgres
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
- db
|
||||
networks:
|
||||
- dreamchat-network
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
|
||||
networks:
|
||||
dreamchat-network:
|
||||
driver: bridge
|
||||
```
|
||||
|
||||
### .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
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: apps/frontend/Dockerfile
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
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
|
||||
|
||||
# Nginx Reverse Proxy (optional)
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./nginx/ssl:/etc/nginx/ssl:ro
|
||||
- model-cache:/model-cache:ro
|
||||
depends_on:
|
||||
- backend
|
||||
- frontend
|
||||
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:20-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:20-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 with Nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy built assets
|
||||
COPY --from=build /app/apps/frontend/dist /usr/share/nginx/html
|
||||
|
||||
# Copy nginx config
|
||||
COPY apps/frontend/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
### frontend/nginx.conf
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Gzip compression
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
|
||||
|
||||
# API proxy
|
||||
location /api {
|
||||
proxy_pass http://backend:3000/api;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
|
||||
# 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";
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Static files
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||
}
|
||||
|
||||
# Health check
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Keycloak Configuration
|
||||
|
||||
### Initial Setup
|
||||
|
||||
1. Access Keycloak admin console: `http://localhost:8080/admin`
|
||||
2. Login with admin credentials
|
||||
3. Create new realm: `dreamchat`
|
||||
4. Create client: `dreamchat-backend`
|
||||
- Client authentication: ON
|
||||
- Authorization: ON
|
||||
- Valid redirect URIs: `http://localhost:3000/*`
|
||||
- Web origins: `http://localhost:3000`
|
||||
|
||||
5. Create client: `dreamchat-frontend`
|
||||
- Client authentication: OFF
|
||||
- Valid redirect URIs: `http://localhost:5173/*`
|
||||
- Web origins: `http://localhost:5173`
|
||||
|
||||
### 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
|
||||
Reference in New Issue
Block a user