Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 5 additions & 49 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,55 +1,11 @@
# ==============================================================================
# JobHelperGuru Production Multi-Stage Dockerfile
# Stage 1: Build React Frontend Assets
# Stage 2: Serve Unified FastAPI Service on Render Free Tier
# ==============================================================================
FROM python:3.11-slim

# ------------------------------------------------------------------------------
# Stage 1: Frontend Builder
# ------------------------------------------------------------------------------
FROM node:20-alpine AS frontend-builder
WORKDIR /app/frontend

# Install dependencies
COPY frontend/package*.json ./
RUN npm ci

# Build static bundle
COPY frontend/ ./
ARG VITE_GOOGLE_CLIENT_ID
ENV VITE_GOOGLE_CLIENT_ID=$VITE_GOOGLE_CLIENT_ID
RUN npm run build

# ------------------------------------------------------------------------------
# Stage 2: Production Python Runtime
# ------------------------------------------------------------------------------
FROM python:3.11-slim AS production
WORKDIR /app

# Install system dependencies (curl for container health checks, libpq-dev for PostgreSQL)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*

# Install Python production dependencies
COPY requirements.txt .
COPY requirements/ ./requirements/
RUN pip install --no-cache-dir -r requirements.txt

# Copy backend source code and initialize local storage directories
COPY backend/ ./backend/
RUN mkdir -p /app/data/uploads

# Copy built frontend assets from Stage 1 into the location expected by FastAPI
COPY --from=frontend-builder /app/frontend/dist ./frontend/dist
COPY render_redirect.py .

# Render assigns port dynamically via $PORT environment variable (defaults to 8000)
EXPOSE 8000
ENV PORT=10000

ENV PORT=8000
ENV PYTHONUNBUFFERED=1
EXPOSE 10000

# Start FastAPI via uvicorn binding to 0.0.0.0 and dynamic $PORT
CMD ["sh", "-c", "uvicorn backend.main:app --host 0.0.0.0 --port ${PORT:-8000}"]
CMD ["python", "render_redirect.py"]
40 changes: 40 additions & 0 deletions render_redirect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

TARGET = "https://jobhelperguru.vercel.app"


class RedirectHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.handle_request()

def do_HEAD(self):
self.handle_request(head_only=True)

def handle_request(self, head_only=False):
if self.path.split("?", 1)[0] in ("/health", "/api/health"):
body = b"ok"
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.send_header("Content-Length", str(len(body)))
self.end_headers()

if not head_only:
self.wfile.write(body)
return

self.send_response(302)
self.send_header("Location", TARGET + self.path)
self.send_header("Cache-Control", "no-store")
self.end_headers()

def log_message(self, format, *args):
print(format % args)


port = int(os.environ.get("PORT", "10000"))

server = ThreadingHTTPServer(("0.0.0.0", port), RedirectHandler)

print(f"Legacy redirect listening on port {port}")
server.serve_forever()
Loading