From c96cde7b7b38950f67c750e1859c038e7ba65eb3 Mon Sep 17 00:00:00 2001 From: Aditya Pulipaka Date: Wed, 1 Apr 2026 15:46:28 +0000 Subject: [PATCH] new server setup --- .dockerignore | 5 ++++ .gitignore | 5 +++- Dockerfile.backend | 17 ++++++++++++++ Dockerfile.frontend | 13 +++++++++++ docker-compose.yml | 57 +++++++++++++++++++++++++++++++++++++++++++++ nginx.conf | 26 +++++++++++++++++++++ server/package.json | 5 ++-- tsconfig.json | 2 +- 8 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile.backend create mode 100644 Dockerfile.frontend create mode 100644 docker-compose.yml create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b95da3b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules/ +server/node_modules/ +server/dist/ +.git/ +.claude/ diff --git a/.gitignore b/.gitignore index d73f687..807e112 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,7 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -package-lock.json \ No newline at end of file +package-lock.json + +.claude/ +uploads/ \ No newline at end of file diff --git a/Dockerfile.backend b/Dockerfile.backend new file mode 100644 index 0000000..64145a6 --- /dev/null +++ b/Dockerfile.backend @@ -0,0 +1,17 @@ +# ---- Build stage ---- +FROM node:22-alpine AS builder +WORKDIR /app +COPY server/package.json server/package-lock.json ./ +RUN npm ci +COPY server/src ./src +COPY server/tsconfig.json ./ +RUN npm run build + +# ---- Runtime stage ---- +FROM node:22-alpine +WORKDIR /app +COPY --from=builder /app/dist ./dist +COPY server/package.json server/package-lock.json ./ +RUN npm ci --omit=dev +EXPOSE 3001 +CMD ["node", "dist/index.js"] diff --git a/Dockerfile.frontend b/Dockerfile.frontend new file mode 100644 index 0000000..ff5ac17 --- /dev/null +++ b/Dockerfile.frontend @@ -0,0 +1,13 @@ +# ---- Build stage ---- +FROM node:22-alpine AS builder +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci +COPY . . +RUN npx vite build + +# ---- Serve stage ---- +FROM nginx:1.27-alpine +COPY --from=builder /app/dist /usr/share/nginx/html +COPY nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 5173 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..adaa7e2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,57 @@ +services: + postgres: + image: postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_USER: labwise + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_DB: labwise_db + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U labwise -d labwise_db"] + interval: 5s + timeout: 5s + retries: 10 + deploy: + resources: + limits: + memory: 256M + + backend: + build: + context: . + dockerfile: Dockerfile.backend + restart: unless-stopped + # Reads all vars from server/.env, then overrides the two that differ in Docker + env_file: ./server/.env + environment: + DATABASE_URL: postgresql://labwise:${POSTGRES_PASSWORD}@postgres:5432/labwise_db + UPLOADS_DIR: /app/uploads + volumes: + - uploads_data:/app/uploads + depends_on: + postgres: + condition: service_healthy + deploy: + resources: + limits: + memory: 192M + + frontend: + build: + context: . + dockerfile: Dockerfile.frontend + restart: unless-stopped + ports: + - "5173:5173" + depends_on: + - backend + deploy: + resources: + limits: + memory: 48M + +volumes: + postgres_data: + uploads_data: diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..fee11d1 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,26 @@ +server { + listen 5173; + root /usr/share/nginx/html; + index index.html; + + # Proxy API and uploads to Express backend + location /api/ { + proxy_pass http://backend:3001; + 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; + } + + location /uploads/ { + proxy_pass http://backend:3001; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + # SPA fallback — all unmatched routes serve index.html + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/server/package.json b/server/package.json index cc299a8..7170fad 100644 --- a/server/package.json +++ b/server/package.json @@ -12,15 +12,16 @@ "@aws-sdk/client-ses": "^3.1013.0", "better-auth": "^1.5.5", "cors": "^2.8.5", + "dotenv": "^17.3.1", "express": "^4.21.2", "express-rate-limit": "^7.5.0", - "multer": "^1.4.5-lts.1", + "multer": "^2.0.0", "pg": "^8.13.3" }, "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^5.0.1", - "@types/multer": "^1.4.12", + "@types/multer": "^2.1.0", "@types/node": "^22.13.10", "@types/pg": "^8.11.11", "tsx": "^4.19.3", diff --git a/tsconfig.json b/tsconfig.json index b1ae1dc..06034b0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,5 +18,5 @@ } }, "include": ["**/*.ts", "**/*.tsx"], - "exclude": ["node_modules", "dist"] + "exclude": ["node_modules", "dist", "server"] }