add docker compose
This commit is contained in:
parent
6f9defe29a
commit
c62af10b02
55
.dockerignore
Normal file
55
.dockerignore
Normal file
@ -0,0 +1,55 @@
|
||||
# Dependencies
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Build output
|
||||
dist
|
||||
build
|
||||
.vite
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# IDE and editor files
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# Docker
|
||||
Dockerfile*
|
||||
docker-compose*.yml
|
||||
.dockerignore
|
||||
|
||||
# Documentation
|
||||
README.md
|
||||
STYLE_GUIDE.md
|
||||
*.md
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
.nyc_output
|
||||
*.test.ts
|
||||
*.test.tsx
|
||||
*.spec.ts
|
||||
*.spec.tsx
|
||||
|
||||
# Misc
|
||||
.cache
|
||||
*.log
|
||||
tmp
|
||||
temp
|
||||
6
.env.example
Normal file
6
.env.example
Normal file
@ -0,0 +1,6 @@
|
||||
# Gemini API Key
|
||||
# Get your API key from: https://aistudio.google.com/app/apikey
|
||||
GEMINI_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# Node Environment (development | production)
|
||||
NODE_ENV=development
|
||||
353
DOCKER_README.md
Normal file
353
DOCKER_README.md
Normal file
@ -0,0 +1,353 @@
|
||||
# Docker Deployment Guide
|
||||
|
||||
This guide explains how to deploy the Pradit application using Docker and Docker Compose.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- Gemini API Key (get from https://aistudio.google.com/app/apikey)
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Setup Environment Variables
|
||||
|
||||
Copy the example environment file and add your Gemini API key:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` and set your `GEMINI_API_KEY`:
|
||||
|
||||
```
|
||||
GEMINI_API_KEY=your_actual_api_key_here
|
||||
```
|
||||
|
||||
### 2. Run Development Mode
|
||||
|
||||
Development mode includes hot reload for rapid iteration:
|
||||
|
||||
```bash
|
||||
docker-compose --profile dev up
|
||||
```
|
||||
|
||||
Access the app at: http://localhost:3000
|
||||
|
||||
### 3. Run Production Mode
|
||||
|
||||
Production mode uses optimized build with nginx:
|
||||
|
||||
```bash
|
||||
docker-compose --profile prod up -d
|
||||
```
|
||||
|
||||
Access the app at: http://localhost:80
|
||||
|
||||
## Docker Compose Profiles
|
||||
|
||||
This project uses Docker Compose profiles to separate dev and prod environments.
|
||||
|
||||
### Development Profile (`dev`)
|
||||
|
||||
- **Port**: 3000
|
||||
- **Hot Reload**: Enabled
|
||||
- **Volume Mounts**: Source code mounted for live changes
|
||||
- **Server**: Vite dev server
|
||||
- **Optimizations**: None (fast rebuild)
|
||||
|
||||
**Commands**:
|
||||
```bash
|
||||
# Start dev server
|
||||
docker-compose --profile dev up
|
||||
|
||||
# Start in background
|
||||
docker-compose --profile dev up -d
|
||||
|
||||
# View logs
|
||||
docker-compose --profile dev logs -f
|
||||
|
||||
# Stop
|
||||
docker-compose --profile dev down
|
||||
```
|
||||
|
||||
### Production Profile (`prod`)
|
||||
|
||||
- **Port**: 80
|
||||
- **Hot Reload**: Disabled
|
||||
- **Build**: Optimized static build
|
||||
- **Server**: Nginx with compression and caching
|
||||
- **Health Check**: Enabled on /health endpoint
|
||||
|
||||
**Commands**:
|
||||
```bash
|
||||
# Build and start production
|
||||
docker-compose --profile prod up -d
|
||||
|
||||
# Rebuild after code changes
|
||||
docker-compose --profile prod up -d --build
|
||||
|
||||
# View logs
|
||||
docker-compose --profile prod logs -f
|
||||
|
||||
# Stop
|
||||
docker-compose --profile prod down
|
||||
```
|
||||
|
||||
## Manual Docker Commands
|
||||
|
||||
### Build Images
|
||||
|
||||
```bash
|
||||
# Development image
|
||||
docker build -f Dockerfile.dev -t pradit:dev .
|
||||
|
||||
# Production image
|
||||
docker build -f Dockerfile -t pradit:prod .
|
||||
```
|
||||
|
||||
### Run Containers
|
||||
|
||||
```bash
|
||||
# Development
|
||||
docker run -p 3000:3000 -v $(pwd):/app -v /app/node_modules \
|
||||
-e GEMINI_API_KEY=your_key pradit:dev
|
||||
|
||||
# Production
|
||||
docker run -p 80:80 pradit:prod
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Development Container
|
||||
|
||||
- **Base**: node:20-alpine
|
||||
- **Package Manager**: pnpm
|
||||
- **Volumes**: Source code mounted for hot reload
|
||||
- **Port**: 3000
|
||||
- **Command**: `pnpm run dev`
|
||||
|
||||
### Production Container
|
||||
|
||||
Multi-stage build for minimal image size:
|
||||
|
||||
1. **Builder Stage**:
|
||||
- Installs dependencies with pnpm
|
||||
- Builds optimized production bundle
|
||||
- Uses node:20-alpine
|
||||
|
||||
2. **Runtime Stage**:
|
||||
- Serves static files with nginx:alpine
|
||||
- Configured for SPA routing
|
||||
- Gzip compression enabled
|
||||
- Security headers added
|
||||
- Health check endpoint at `/health`
|
||||
|
||||
## Configuration Files
|
||||
|
||||
### Dockerfile
|
||||
Production multi-stage build configuration.
|
||||
|
||||
### Dockerfile.dev
|
||||
Development container with hot reload support.
|
||||
|
||||
### docker-compose.yml
|
||||
Orchestration for both dev and prod profiles.
|
||||
|
||||
### nginx.conf
|
||||
Nginx configuration for production:
|
||||
- SPA routing (serves index.html for all routes)
|
||||
- Gzip compression
|
||||
- Static asset caching (1 year)
|
||||
- Security headers
|
||||
- Health check endpoint
|
||||
|
||||
### .dockerignore
|
||||
Excludes unnecessary files from Docker build context:
|
||||
- node_modules
|
||||
- Build artifacts
|
||||
- Environment files
|
||||
- IDE configurations
|
||||
- Documentation
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `GEMINI_API_KEY` | Yes | API key for Gemini AI |
|
||||
| `NODE_ENV` | No | Environment mode (development/production) |
|
||||
|
||||
**Security Note**: Never commit `.env` file. Use `.env.example` as template.
|
||||
|
||||
## Port Configuration
|
||||
|
||||
| Service | Port | Description |
|
||||
|---------|------|-------------|
|
||||
| Development | 3000 | Vite dev server |
|
||||
| Production | 80 | Nginx web server |
|
||||
|
||||
To use different ports, edit `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "8080:80" # Host:Container
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```bash
|
||||
# Find process using port 3000
|
||||
netstat -ano | findstr :3000 # Windows
|
||||
lsof -i :3000 # Linux/Mac
|
||||
|
||||
# Change port in docker-compose.yml
|
||||
ports:
|
||||
- "3001:3000"
|
||||
```
|
||||
|
||||
### API Key Not Working
|
||||
|
||||
Ensure `.env` file exists and contains valid key:
|
||||
```bash
|
||||
cat .env # Linux/Mac
|
||||
type .env # Windows
|
||||
```
|
||||
|
||||
Restart containers after changing `.env`:
|
||||
```bash
|
||||
docker-compose --profile dev down
|
||||
docker-compose --profile dev up
|
||||
```
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
Check logs for errors:
|
||||
```bash
|
||||
docker-compose --profile dev logs
|
||||
docker-compose --profile prod logs
|
||||
```
|
||||
|
||||
Remove containers and rebuild:
|
||||
```bash
|
||||
docker-compose down -v
|
||||
docker-compose --profile prod up -d --build
|
||||
```
|
||||
|
||||
### Volume Permission Issues (Linux)
|
||||
|
||||
If encountering permission issues with mounted volumes:
|
||||
```bash
|
||||
# Add user ID to docker-compose.yml
|
||||
user: "${UID}:${GID}"
|
||||
```
|
||||
|
||||
### Build Cache Issues
|
||||
|
||||
Clear Docker build cache:
|
||||
```bash
|
||||
docker builder prune -a
|
||||
docker-compose build --no-cache
|
||||
```
|
||||
|
||||
## Health Checks
|
||||
|
||||
Production container includes health check:
|
||||
|
||||
```bash
|
||||
# Check container health
|
||||
docker ps
|
||||
|
||||
# Manual health check
|
||||
curl http://localhost/health
|
||||
```
|
||||
|
||||
## Logs and Debugging
|
||||
|
||||
```bash
|
||||
# Follow logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Specific service logs
|
||||
docker-compose --profile dev logs pradit-dev
|
||||
docker-compose --profile prod logs pradit-prod
|
||||
|
||||
# Enter running container
|
||||
docker exec -it pradit-dev sh
|
||||
docker exec -it pradit-prod sh
|
||||
```
|
||||
|
||||
## Cleaning Up
|
||||
|
||||
```bash
|
||||
# Stop and remove containers
|
||||
docker-compose down
|
||||
|
||||
# Remove containers and volumes
|
||||
docker-compose down -v
|
||||
|
||||
# Remove images
|
||||
docker rmi pradit:dev pradit:prod
|
||||
|
||||
# Full cleanup (all unused Docker resources)
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
For cloud deployment (AWS, GCP, Azure, etc.):
|
||||
|
||||
1. Build and tag image:
|
||||
```bash
|
||||
docker build -t your-registry/pradit:latest .
|
||||
```
|
||||
|
||||
2. Push to registry:
|
||||
```bash
|
||||
docker push your-registry/pradit:latest
|
||||
```
|
||||
|
||||
3. Deploy to orchestration platform (Kubernetes, ECS, etc.)
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Production Build
|
||||
|
||||
- Tree shaking removes unused code
|
||||
- Minification reduces bundle size
|
||||
- Gzip compression (nginx)
|
||||
- Static asset caching (1 year)
|
||||
- Multi-stage build minimizes image size
|
||||
|
||||
### Development Build
|
||||
|
||||
- Fast rebuild with hot module replacement
|
||||
- Source maps for debugging
|
||||
- No minification for faster builds
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Never commit API keys** - Use environment variables
|
||||
2. **Use multi-stage builds** - Minimize attack surface
|
||||
3. **Run as non-root** - Production nginx runs as nginx user
|
||||
4. **Keep images updated** - Regularly update base images
|
||||
5. **Scan for vulnerabilities** - Use `docker scan pradit:prod`
|
||||
6. **Use secrets management** - For production, use Docker secrets or cloud provider solutions
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Docker Documentation](https://docs.docker.com/)
|
||||
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||
- [Vite Documentation](https://vitejs.dev/)
|
||||
- [Nginx Documentation](https://nginx.org/en/docs/)
|
||||
|
||||
## Support
|
||||
|
||||
For issues specific to Docker setup, check:
|
||||
1. Docker daemon is running
|
||||
2. Environment variables are set correctly
|
||||
3. Ports are not already in use
|
||||
4. Sufficient disk space for images and containers
|
||||
|
||||
For application issues, refer to main [README.md](README.md).
|
||||
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@ -0,0 +1,35 @@
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
# Install pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN pnpm run build
|
||||
|
||||
# Production stage
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy built assets from builder stage
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
# Copy nginx configuration
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Start nginx
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
23
Dockerfile.dev
Normal file
23
Dockerfile.dev
Normal file
@ -0,0 +1,23 @@
|
||||
# Development Dockerfile
|
||||
FROM node:20-alpine
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install pnpm globally
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Copy package files
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
|
||||
# Install dependencies
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Expose development port
|
||||
EXPOSE 3000
|
||||
|
||||
# Start development server with hot reload
|
||||
CMD ["pnpm", "run", "dev"]
|
||||
51
docker-compose.yml
Normal file
51
docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# Development service
|
||||
pradit-dev:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
container_name: pradit-dev
|
||||
profiles:
|
||||
- dev
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- .:/app
|
||||
- /app/node_modules
|
||||
environment:
|
||||
- NODE_ENV=development
|
||||
- GEMINI_API_KEY=${GEMINI_API_KEY}
|
||||
command: pnpm run dev
|
||||
networks:
|
||||
- pradit-network
|
||||
restart: unless-stopped
|
||||
|
||||
# Production service
|
||||
pradit-prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- GEMINI_API_KEY=${GEMINI_API_KEY}
|
||||
container_name: pradit-prod
|
||||
profiles:
|
||||
- prod
|
||||
ports:
|
||||
- "80:80"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
networks:
|
||||
- pradit-network
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
pradit-network:
|
||||
driver: bridge
|
||||
35
nginx.conf
Normal file
35
nginx.conf
Normal file
@ -0,0 +1,35 @@
|
||||
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/x-javascript application/xml+rss application/javascript application/json;
|
||||
|
||||
# Security headers
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Cache static assets
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# SPA routing - serve index.html for all routes
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Health check endpoint
|
||||
location /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user