Mananjp commited on
Commit
2864f3c
·
1 Parent(s): 9ff5f0f

feat: unified nginx proxy deployment

Browse files
Files changed (5) hide show
  1. .github/workflows/publish-ghcr.yml +8 -27
  2. Dockerfile +55 -0
  3. frontend/app.py +3 -3
  4. nginx.conf +48 -0
  5. start.sh +24 -0
.github/workflows/publish-ghcr.yml CHANGED
@@ -32,40 +32,21 @@ jobs:
32
  username: ${{ github.actor }}
33
  password: ${{ secrets.GITHUB_TOKEN }}
34
 
35
- # Backend Build & Push
36
- - name: Extract metadata (tags, labels) for Backend
37
- id: meta-backend
38
  uses: docker/metadata-action@v5
39
  with:
40
- images: ${{ env.REGISTRY }}/${{ env.REPO_LC }}-backend
41
  tags: |
42
  type=raw,value=latest
43
  type=sha
44
 
45
- - name: Build and push Backend image
46
  uses: docker/build-push-action@v5
47
  with:
48
  context: .
49
- file: Dockerfile.backend
50
  push: true
51
- tags: ${{ steps.meta-backend.outputs.tags }}
52
- labels: ${{ steps.meta-backend.outputs.labels }}
53
-
54
- # Frontend Build & Push
55
- - name: Extract metadata (tags, labels) for Frontend
56
- id: meta-frontend
57
- uses: docker/metadata-action@v5
58
- with:
59
- images: ${{ env.REGISTRY }}/${{ env.REPO_LC }}-frontend
60
- tags: |
61
- type=raw,value=latest
62
- type=sha
63
-
64
- - name: Build and push Frontend image
65
- uses: docker/build-push-action@v5
66
- with:
67
- context: .
68
- file: Dockerfile.frontend
69
- push: true
70
- tags: ${{ steps.meta-frontend.outputs.tags }}
71
- labels: ${{ steps.meta-frontend.outputs.labels }}
 
32
  username: ${{ github.actor }}
33
  password: ${{ secrets.GITHUB_TOKEN }}
34
 
35
+ # Unified Build & Push
36
+ - name: Extract metadata (tags, labels) for Unified Image
37
+ id: meta-unified
38
  uses: docker/metadata-action@v5
39
  with:
40
+ images: ${{ env.REGISTRY }}/${{ env.REPO_LC }}-unified
41
  tags: |
42
  type=raw,value=latest
43
  type=sha
44
 
45
+ - name: Build and push Unified image
46
  uses: docker/build-push-action@v5
47
  with:
48
  context: .
49
+ file: Dockerfile
50
  push: true
51
+ tags: ${{ steps.meta-unified.outputs.tags }}
52
+ labels: ${{ steps.meta-unified.outputs.labels }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Multi-stage build for optimized unified (frontend + backend) deployment
2
+ FROM python:3.11-slim as builder
3
+
4
+ WORKDIR /app
5
+
6
+ # Install build dependencies
7
+ RUN apt-get update && apt-get install -y --no-install-recommends \
8
+ build-essential \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Copy and install requirements
12
+ COPY frontend/requirements.txt requirements.txt
13
+ COPY backend/requirements.txt backend_requirements.txt
14
+
15
+ RUN pip install --upgrade pip setuptools wheel && \
16
+ pip install --no-cache-dir -r requirements.txt && \
17
+ pip install --no-cache-dir -r backend_requirements.txt
18
+
19
+ # Final stage
20
+ FROM python:3.11-slim
21
+
22
+ WORKDIR /app
23
+
24
+ # Install runtime dependencies for executing multi-language code and Nginx for routing
25
+ RUN apt-get update && apt-get install -y --no-install-recommends \
26
+ nodejs \
27
+ npm \
28
+ g++ \
29
+ default-jdk \
30
+ dnsutils \
31
+ curl \
32
+ nginx \
33
+ && rm -rf /var/lib/apt/lists/*
34
+
35
+ # Copy Python packages from builder
36
+ COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
37
+ COPY --from=builder /usr/local/bin /usr/local/bin
38
+
39
+ # Copy application files
40
+ COPY frontend/ frontend/
41
+ COPY backend/ backend/
42
+ COPY start.sh start.sh
43
+ COPY nginx.conf /etc/nginx/nginx.conf
44
+
45
+ # Make start script executable
46
+ RUN chmod +x start.sh
47
+
48
+ # Expose the single proxy port (7860 for Hugging Face or Railway dynamic PORT)
49
+ EXPOSE 7860
50
+
51
+ # Proxy Configuration
52
+ ENV PORT=7860
53
+
54
+ # Run both Streamlit app and FastAPI using the wrapper script
55
+ CMD ["./start.sh"]
frontend/app.py CHANGED
@@ -123,10 +123,10 @@ for (let num of numbers) {
123
  # ============================================================================
124
 
125
  # The URL used by Streamlit (server) to contact FastAPI (server)
126
- BACKEND_URL = os.getenv("BACKEND_URL", "https://examide-backend-production.up.railway.app")
127
 
128
- # The URL used by the browser (client JS) to contact FastAPI
129
- PUBLIC_BACKEND_URL = os.getenv("PUBLIC_BACKEND_URL", "https://examide-backend-production.up.railway.app")
130
 
131
 
132
  # ============================================================================
 
123
  # ============================================================================
124
 
125
  # The URL used by Streamlit (server) to contact FastAPI (server)
126
+ BACKEND_URL = os.getenv("BACKEND_URL", "http://127.0.0.1:8000")
127
 
128
+ # The URL used by the browser (client JS) to contact the unified Nginx proxy
129
+ PUBLIC_BACKEND_URL = os.getenv("PUBLIC_BACKEND_URL", "")
130
 
131
 
132
  # ============================================================================
nginx.conf ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ worker_processes 1;
2
+
3
+ events {
4
+ worker_connections 1024;
5
+ }
6
+
7
+ http {
8
+ include mime.types;
9
+ default_type application/octet-stream;
10
+
11
+ # Increase maximum upload size if needed (e.g. for student code or large bodies)
12
+ client_max_body_size 50M;
13
+
14
+ server {
15
+ # This port will be replaced dynamically in start.sh
16
+ listen 7860;
17
+ server_name _;
18
+
19
+ # Route API to FastAPI
20
+ location /api/ {
21
+ proxy_pass http://127.0.0.1:8000/api/;
22
+ proxy_set_header Host $host;
23
+ proxy_set_header X-Real-IP $remote_addr;
24
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25
+ }
26
+
27
+ # WebSocket support for Streamlit
28
+ location /_stcore/stream {
29
+ proxy_pass http://127.0.0.1:8501/_stcore/stream;
30
+ proxy_http_version 1.1;
31
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
32
+ proxy_set_header Host $host;
33
+ proxy_set_header Upgrade $http_upgrade;
34
+ proxy_set_header Connection "upgrade";
35
+ proxy_read_timeout 86400;
36
+ }
37
+
38
+ # Route remaining to Streamlit
39
+ location / {
40
+ proxy_pass http://127.0.0.1:8501/;
41
+ proxy_set_header Host $host;
42
+ proxy_set_header X-Real-IP $remote_addr;
43
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
44
+ proxy_set_header Upgrade $http_upgrade;
45
+ proxy_set_header Connection "upgrade";
46
+ }
47
+ }
48
+ }
start.sh ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Update Nginx listen port based on environment variable (default 7860 for HF Spaces)
4
+ sed -i "s/listen 7860;/listen ${PORT:-7860};/g" /etc/nginx/nginx.conf
5
+
6
+ # Start the FastAPI backend in the background on localhost
7
+ cd /app/backend
8
+ uvicorn main:app --host 127.0.0.1 --port 8000 &
9
+
10
+ # Go back to /app
11
+ cd /app
12
+
13
+ # Start the Streamlit frontend in the background on localhost
14
+ streamlit run frontend/app.py \
15
+ --server.port=8501 \
16
+ --server.address=127.0.0.1 \
17
+ --server.headless=true \
18
+ --server.enableCORS=false \
19
+ --server.enableXsrfProtection=false \
20
+ --server.enableWebsocketCompression=false &
21
+
22
+ # Start Nginx in the foreground to keep the container alive
23
+ echo "Starting Nginx Proxy on port ${PORT:-7860}..."
24
+ nginx -g "daemon off;"