Spaces:
Sleeping
Sleeping
| # ============================================================ | |
| # STAGE 1: Build the React/Vite Frontend | |
| # ============================================================ | |
| FROM node:20-alpine AS frontend-build | |
| WORKDIR /app/frontend | |
| # Copy package files and install dependencies | |
| COPY F_Pro/package.json F_Pro/package-lock.json ./ | |
| RUN npm ci | |
| # Copy the rest of the frontend source | |
| COPY F_Pro/ . | |
| # Build-time env vars that Vite bakes into the static bundle. | |
| # Pass them with --build-arg in `docker build` or set them | |
| # as HuggingFace Space secrets (they become ARGs automatically). | |
| ARG VITE_GOOGLE_CLIENT_ID | |
| ARG VITE_STRIPE_PUBLISHABLE_KEY | |
| # For HuggingFace the app is served on port 7860, so the API | |
| # lives on the same host. Override these if you use an external backend. | |
| ARG VITE_API_BASE_URL=http://localhost:7860/api | |
| ARG VITE_WS_URL=ws://localhost:7860/ws | |
| ENV VITE_GOOGLE_CLIENT_ID=$VITE_GOOGLE_CLIENT_ID | |
| ENV VITE_STRIPE_PUBLISHABLE_KEY=$VITE_STRIPE_PUBLISHABLE_KEY | |
| ENV VITE_API_BASE_URL=$VITE_API_BASE_URL | |
| ENV VITE_WS_URL=$VITE_WS_URL | |
| RUN npm run build | |
| # Output is in /app/frontend/dist | |
| # ============================================================ | |
| # STAGE 2: Build the Spring Boot Backend | |
| # ============================================================ | |
| FROM maven:3.9.6-eclipse-temurin-21 AS backend-build | |
| WORKDIR /app/backend | |
| # Cache Maven dependencies separately from source | |
| COPY quran-app-backend/pom.xml . | |
| RUN mvn dependency:go-offline -B | |
| # Build the JAR | |
| COPY quran-app-backend/src ./src | |
| RUN mvn clean package -DskipTests | |
| # Output is in /app/backend/target/*.jar | |
| # ============================================================ | |
| # STAGE 3: Final runtime image | |
| # ============================================================ | |
| FROM eclipse-temurin:21-jre-jammy | |
| WORKDIR /app | |
| # ---------- system packages ---------- | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| nginx \ | |
| ffmpeg \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # ---------- Nginx config ---------- | |
| # Nginx listens on 7860 (the port HuggingFace Spaces exposes). | |
| # Static files are served directly; /api/** and /ws/** are proxied | |
| # to the Spring Boot process running on 3000 internally. | |
| RUN rm -f /etc/nginx/sites-enabled/default | |
| COPY <<'NGINX_EOF' /etc/nginx/conf.d/quranapp.conf | |
| server { | |
| listen 7860; | |
| server_name _; | |
| # Serve the React SPA | |
| root /app/static; | |
| index index.html; | |
| # API proxy → Spring Boot | |
| location /api/ { | |
| proxy_pass http://127.0.0.1:3000/api/; | |
| proxy_http_version 1.1; | |
| 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_read_timeout 300s; | |
| proxy_send_timeout 300s; | |
| proxy_connect_timeout 300s; | |
| client_max_body_size 50M; | |
| } | |
| # WebSocket proxy → Spring Boot | |
| location /ws/ { | |
| proxy_pass http://127.0.0.1:3000/ws/; | |
| proxy_http_version 1.1; | |
| proxy_set_header Upgrade $http_upgrade; | |
| proxy_set_header Connection "upgrade"; | |
| proxy_set_header Host $host; | |
| proxy_read_timeout 3600s; | |
| } | |
| # SPA fallback — all other paths return index.html | |
| location / { | |
| try_files $uri $uri/ /index.html; | |
| } | |
| error_page 500 502 503 504 /50x.html; | |
| location = /50x.html { | |
| root /usr/share/nginx/html; | |
| } | |
| } | |
| NGINX_EOF | |
| # ---------- Copy built artifacts ---------- | |
| COPY --from=frontend-build /app/frontend/dist /app/static | |
| COPY --from=backend-build /app/backend/target/*.jar /app/app.jar | |
| # ---------- Startup script ---------- | |
| # HuggingFace Spaces require a single process entry point. | |
| # We start Spring Boot in the background, then hand control to Nginx. | |
| COPY <<'STARTUP_EOF' /app/start.sh | |
| #!/bin/bash | |
| set -e | |
| echo "==> Starting Spring Boot on port 3000..." | |
| java -jar /app/app.jar & | |
| echo "==> Waiting for Spring Boot to be ready..." | |
| until curl -sf http://127.0.0.1:3000/actuator/health > /dev/null 2>&1; do | |
| sleep 2 | |
| done | |
| echo "==> Spring Boot is ready. Starting Nginx on port 7860..." | |
| nginx -g "daemon off;" | |
| STARTUP_EOF | |
| RUN chmod +x /app/start.sh | |
| # HuggingFace Spaces only expose port 7860 | |
| EXPOSE 7860 | |
| CMD ["/app/start.sh"] | |