# QuantumShield - Combined Production Dockerfile # Runs both Next.js frontend and FastAPI backend in a single container # Optimized for Hugging Face Spaces deployment FROM python:3.11-slim as base # Install Node.js RUN apt-get update && apt-get install -y \ curl \ gcc \ g++ \ nginx \ && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get install -y nodejs \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # ============== Backend Setup ============== COPY backend/requirements.txt ./backend/ RUN pip install --no-cache-dir -r backend/requirements.txt COPY backend/ ./backend/ COPY models/ ./models/ # Create data directory (data will be downloaded from Google Drive at startup) RUN mkdir -p ./data # ============== Frontend Setup ============== COPY frontend/package*.json ./frontend/ WORKDIR /app/frontend RUN npm install COPY frontend/ . # Build frontend with API URL pointing to same origin ENV NEXT_PUBLIC_API_URL="" RUN npm run build # ============== Nginx Config (Reverse Proxy) ============== WORKDIR /app RUN cat > /etc/nginx/nginx.conf << 'EOF' worker_processes 1; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream frontend { server 127.0.0.1:3000; } upstream backend { server 127.0.0.1:8000; } server { listen 7860; # API routes go to backend location /api { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 60s; proxy_read_timeout 60s; } # Health check location /health { proxy_pass http://backend; } # Everything else goes to frontend location / { proxy_pass http://frontend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; } } } EOF # ============== Start Script ============== RUN cat > /app/start.sh << 'EOF' #!/bin/bash echo "Starting QuantumShield..." # Start nginx (binds to port 7860 for HF Spaces) nginx # Start backend (will download data on first run) cd /app python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000 & BACKEND_PID=$! # Wait for backend to initialize sleep 5 # Start frontend cd /app/frontend PORT=3000 npm start & FRONTEND_PID=$! # Keep container alive - restart services if they die while true; do if ! kill -0 $BACKEND_PID 2>/dev/null; then echo "Backend died, restarting..." cd /app python -m uvicorn backend.main:app --host 127.0.0.1 --port 8000 & BACKEND_PID=$! fi if ! kill -0 $FRONTEND_PID 2>/dev/null; then echo "Frontend died, restarting..." cd /app/frontend PORT=3000 npm start & FRONTEND_PID=$! fi sleep 30 done EOF RUN chmod +x /app/start.sh # Set environment variable for backend to find models/data ENV PYTHONPATH=/app # HF Spaces uses port 7860 EXPOSE 7860 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=5 \ CMD curl -f http://localhost:7860/health || exit 1 # Start all services CMD ["/app/start.sh"]