From 6227fffe4c8d4d23addff28f1073d4ba80310d4f Mon Sep 17 00:00:00 2001 From: Matiss Jurevics Date: Tue, 6 Jan 2026 16:35:59 +0000 Subject: [PATCH] feat: Configure production Docker deployment with Nginx, health checks, and SQLite data persistence. --- client/Dockerfile | 22 ++++++++++++++++++---- client/nginx.conf | 34 ++++++++++++++++++++++++++++++++++ docker-compose.yml | 29 ++++++++++++++++------------- server/Dockerfile | 16 ++++++++++++---- server/db.js | 4 +++- 5 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 client/nginx.conf diff --git a/client/Dockerfile b/client/Dockerfile index 8c2f99d..f1b9101 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -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;"] diff --git a/client/nginx.conf b/client/nginx.conf new file mode 100644 index 0000000..aa360d5 --- /dev/null +++ b/client/nginx.conf @@ -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"; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index dbfc83b..0c0a6c4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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: diff --git a/server/Dockerfile b/server/Dockerfile index 4fb793a..e16bed5 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -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"] diff --git a/server/db.js b/server/db.js index 03e7f08..07371c5 100644 --- a/server/db.js +++ b/server/db.js @@ -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