DB, Collections, Search

This commit is contained in:
Stefan Hardegger
2025-11-21 07:53:37 +01:00
parent c8eb6237c4
commit 8a03edbb88
67 changed files with 17703 additions and 103 deletions

81
docker/Dockerfile Normal file
View File

@@ -0,0 +1,81 @@
# Stage 1: Dependencies
FROM node:22-alpine AS deps
WORKDIR /app
# Install dependencies for building native modules
RUN apk add --no-cache \
libc6-compat \
openssl \
python3 \
make \
g++
# Copy package files
COPY package.json package-lock.json ./
COPY prisma ./prisma
# Install dependencies
RUN npm ci
# Generate Prisma Client
RUN npx prisma generate
# Stage 2: Builder
FROM node:22-alpine AS builder
WORKDIR /app
# Install openssl for Prisma
RUN apk add --no-cache openssl
# Copy dependencies from deps stage
COPY --from=deps /app/node_modules ./node_modules
# Copy source code
COPY . .
# Generate Prisma Client again for builder context
RUN npx prisma generate
# Build Next.js application
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN npm run build
# Stage 3: Runner
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
# Install runtime dependencies
RUN apk add --no-cache openssl
# Create non-root user
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# Copy necessary files with ownership set during copy (more efficient)
COPY --chown=nextjs:nodejs --from=builder /app/public ./public
COPY --chown=nextjs:nodejs --from=builder /app/.next/standalone ./
COPY --chown=nextjs:nodejs --from=builder /app/.next/static ./.next/static
# Copy node_modules for Prisma CLI and seed script (Prisma CLI has 33+ dependencies)
COPY --chown=nextjs:nodejs --from=builder /app/node_modules ./node_modules
COPY --chown=nextjs:nodejs --from=builder /app/prisma ./prisma
# Copy entrypoint script
COPY --chown=nextjs:nodejs --from=builder /app/docker/entrypoint.sh ./entrypoint.sh
RUN chmod +x ./entrypoint.sh
# Switch to non-root user
USER nextjs
# Expose port
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
# Start the application with automatic migrations
ENTRYPOINT ["./entrypoint.sh"]

18
docker/entrypoint.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
set -e
echo "🔄 Running database migrations..."
# Check if migrations directory exists and has files
if [ -d "prisma/migrations" ] && [ "$(ls -A prisma/migrations 2>/dev/null)" ]; then
echo "Found migration files, running migrate deploy..."
node_modules/.bin/prisma migrate deploy
else
echo "No migration files found, running db push..."
node_modules/.bin/prisma db push --accept-data-loss
fi
echo "🌱 Seeding database (if needed)..."
node_modules/.bin/tsx prisma/seed.ts || echo "⚠️ Seed failed or already completed, continuing..."
echo "🚀 Starting application..."
exec node server.js

101
docker/nginx.conf Normal file
View File

@@ -0,0 +1,101 @@
events {
worker_connections 1024;
}
http {
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
# Upstream Next.js app
upstream nextjs_app {
server app:3000;
}
# HTTP server - redirect to HTTPS
server {
listen 80;
server_name _;
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
server_name _;
# SSL configuration
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 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;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# Max body size for file uploads
client_max_body_size 10M;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Rate limiting for auth endpoints
location ~ ^/(api/auth|login|register) {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://nextjs_app;
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;
}
# Rate limiting for API endpoints
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://nextjs_app;
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;
}
# General rate limiting for all other requests
location / {
limit_req zone=general burst=20 nodelay;
proxy_pass http://nextjs_app;
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;
# Cache static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://nextjs_app;
proxy_cache_valid 200 30d;
add_header Cache-Control "public, immutable";
}
}
}
}

35
docker/ssl/README.md Normal file
View File

@@ -0,0 +1,35 @@
# SSL Certificates
This directory should contain SSL certificates for HTTPS.
## Development
For local development, you can generate self-signed certificates:
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout key.pem -out cert.pem \
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
```
## Production
For production, use certificates from a trusted Certificate Authority like:
- Let's Encrypt (recommended, free)
- Your domain provider
- Commercial CA
### Let's Encrypt with Certbot
```bash
sudo certbot certonly --standalone -d yourdomain.com
sudo cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ./cert.pem
sudo cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ./key.pem
```
## Required Files
- `cert.pem` - SSL certificate
- `key.pem` - Private key
**Important:** Never commit real SSL certificates to version control!