From e32d2e4ed32bc687f452e2d7a5c4e6efe5ffc2e6 Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:14:43 -0800 Subject: [PATCH] fix: Add docker config and update domain to 777wolfpack.runfoo.run --- backend/Dockerfile | 38 ++++++++++++++++++++ docker-compose.yml | 84 +++++++++++++++++++++++++++++++++++++++++++++ frontend/Dockerfile | 28 +++++++++++++++ frontend/nginx.conf | 29 ++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 backend/Dockerfile create mode 100644 docker-compose.yml create mode 100644 frontend/Dockerfile create mode 100644 frontend/nginx.conf diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..fa8a331 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,38 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ +# Copy prisma directory if it exists, otherwise we'll handle it +COPY prisma ./prisma/ + +# Install dependencies +RUN npm ci + +# Copy source +COPY . . + +# Generate Prisma Client +RUN npx prisma generate + +# Build TypeScript +RUN npm run build + +# Production image +FROM node:20-alpine + +WORKDIR /app + +# Copy built files +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/prisma ./prisma +COPY --from=builder /app/package*.json ./ + +# Run as non-root +USER node + +EXPOSE 3000 + +CMD ["node", "dist/server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..146008b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,84 @@ +version: '3.8' + +services: + db: + image: postgres:15-alpine + environment: + POSTGRES_DB: ca_grow_ops + POSTGRES_USER: ca_grow_ops + POSTGRES_PASSWORD: ${DB_PASSWORD} + volumes: + - db_data:/var/lib/postgresql/data + restart: unless-stopped + networks: + - internal + healthcheck: + test: [ "CMD-SHELL", "pg_isready -U ca_grow_ops" ] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + restart: unless-stopped + networks: + - internal + healthcheck: + test: [ "CMD", "redis-cli", "ping" ] + interval: 10s + timeout: 5s + retries: 5 + + backend: + build: + context: ./backend + dockerfile: Dockerfile + environment: + DATABASE_URL: postgresql://ca_grow_ops:${DB_PASSWORD}@db:5432/ca_grow_ops + REDIS_URL: redis://redis:6379 + JWT_SECRET: ${JWT_SECRET} + JWT_ACCESS_EXPIRY: 15m + JWT_REFRESH_EXPIRY: 7d + NODE_ENV: production + PORT: 3000 + depends_on: + db: + condition: service_healthy + redis: + condition: service_healthy + restart: unless-stopped + networks: + - internal + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:3000/healthz" ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + environment: + VITE_API_URL: /api + labels: + - "traefik.enable=true" + - "traefik.http.routers.ca-grow-ops.rule=Host(`777wolfpack.runfoo.run`)" + - "traefik.http.routers.ca-grow-ops.entrypoints=websecure" + - "traefik.http.routers.ca-grow-ops.tls.certresolver=myresolver" + - "traefik.http.services.ca-grow-ops.loadbalancer.server.port=80" + depends_on: + - backend + restart: unless-stopped + networks: + - internal + - traefik-public + +networks: + internal: + traefik-public: + external: true + +volumes: + db_data: diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..7d6a71d --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,28 @@ +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy source +COPY . . + +# Build for production +RUN npm run build + +# Production image with Nginx +FROM nginx:alpine + +# Copy built files +COPY --from=builder /app/dist /usr/share/nginx/html + +# Copy Nginx config +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..b401510 --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,29 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + # API proxy + location /api { + proxy_pass http://backend:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + 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; + } + + # Frontend SPA routing + location / { + try_files $uri $uri/ /index.html; + } + + # 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; +}