File size: 3,628 Bytes
9c750b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# 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"]