feat: Configure production Docker deployment with Nginx, health checks, and SQLite data persistence.

This commit is contained in:
2026-01-06 16:35:59 +00:00
parent 7f27d0a064
commit 6227fffe4c
5 changed files with 83 additions and 22 deletions

View File

@@ -1,13 +1,27 @@
FROM node:20-alpine
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 5173
# Production stage
FROM nginx:alpine
CMD ["npm", "run", "dev", "--", "--host"]
# Copy built assets
COPY --from=builder /app/dist /usr/share/nginx/html
# Copy nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:80/ || exit 1
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

34
client/nginx.conf Normal file
View File

@@ -0,0 +1,34 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
# Proxy API requests to backend
location /api {
proxy_pass http://server: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;
proxy_cache_bypass $http_upgrade;
}
# SPA fallback - serve index.html for all routes
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

View File

@@ -3,10 +3,6 @@ services:
build:
context: .
dockerfile: server/Dockerfile
# Remove fixed port binding for production - let Coolify/reverse proxy handle routing
# Uncomment below for local development:
# ports:
# - "3000:3000"
expose:
- "3000"
volumes:
@@ -15,22 +11,29 @@ services:
- PORT=3000
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-123456}
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
client:
build:
context: ./client
dockerfile: Dockerfile
# Remove fixed port binding for production - let Coolify/reverse proxy handle routing
# Uncomment below for local development:
# ports:
# - "5173:5173"
expose:
- "5173"
ports:
- "80:80"
depends_on:
- server
environment:
- VITE_API_URL=http://server:3000
server:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80/"]
interval: 30s
timeout: 3s
retries: 3
start_period: 5s
volumes:
eventy_data:

View File

@@ -2,17 +2,25 @@ FROM node:20-alpine
WORKDIR /app
# Copy root package files
# Copy package files
COPY package.json package-lock.json* ./
# Install production dependencies
# Install production dependencies only
RUN npm ci --omit=dev
# Copy server source code
COPY server ./server
# Expose port
# Create data directory for SQLite
RUN mkdir -p /app/data
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
ENV NODE_ENV=production
ENV PORT=3000
EXPOSE 3000
# Start server
CMD ["node", "server/index.js"]

View File

@@ -1,7 +1,9 @@
const Database = require('better-sqlite3');
const path = require('path');
const dbPath = path.resolve(__dirname, 'eventy.db');
// Use /app/data for production (Docker volume), fallback to local for dev
const dataDir = process.env.NODE_ENV === 'production' ? '/app/data' : __dirname;
const dbPath = path.join(dataDir, 'eventy.db');
const db = new Database(dbPath);
// Enable WAL mode for better concurrency