-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
141 lines (117 loc) · 5.39 KB
/
Copy pathDockerfile
File metadata and controls
141 lines (117 loc) · 5.39 KB
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
# Multi-stage Dockerfile for Movie Recommendation System
# Stage 1: Build React frontend
# Stage 2: Build ETL artifacts
# Stage 3: Lightweight runtime
FROM node:24-slim AS frontend_builder
WORKDIR /frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
ENV VITE_BASE_PATH=/ui/
RUN npm run build
FROM python:3.11-slim AS builder
WORKDIR /app
# Install build dependencies
# hadolint ignore=DL3008
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cargo \
&& rm -rf /var/lib/apt/lists/*
# Copy uv binary for lightning-fast dependency installation
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# Install Python dependencies
COPY requirements.txt .
RUN uv pip install --system --no-cache -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu --index-strategy unsafe-best-match
# Copy source code
COPY etl/ ./etl/
COPY backend/ ./backend/
COPY scripts/ ./scripts/
COPY frontend/streamlit_app.py ./frontend/streamlit_app.py
COPY REVISION* ./
# Build and install the Rust core extension module
RUN uv pip install --system maturin && \
maturin build --manifest-path backend/rust_core/Cargo.toml --release --interpreter python3.11 --out dist && \
uv pip install --system --no-cache dist/*.whl
# Fail image builds early if synced Python source has a syntax error.
RUN python -m compileall backend etl scripts frontend/streamlit_app.py
# Copy Pre-computed Models and Data (present in production builds; skipped in CI)
# Use COPY with a wildcard so the layer is a no-op when the directories are absent
# rather than failing with "no source files were specified".
# hadolint ignore=DL3059
RUN mkdir -p models data/processed data/evaluation
COPY models/ ./models/
COPY data/processed/ ./data/processed/
COPY data/evaluation/ ./data/evaluation/
# Create other directories
# hadolint ignore=DL3059
RUN mkdir -p data/raw logs
# Pre-download serving model files to make container startup instant
# hadolint ignore=DL3059
RUN python -c "from backend.models.model_loader import ensure_model_files, default_artifacts_for_serving_profile; from pathlib import Path; ensure_model_files(Path('backend/models'), default_artifacts_for_serving_profile())"
# -------------------------------------------
# Stage 2: Runtime image
FROM python:3.11-slim AS runtime
WORKDIR /app
# Install runtime dependencies only
# hadolint ignore=DL3008
RUN apt-get update && apt-get install -y --no-install-recommends \
libgomp1 \
&& rm -rf /var/lib/apt/lists/*
# Copy installed packages from builder
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
# Copy application code
COPY --from=builder /app /app
COPY --from=frontend_builder /frontend/dist /app/frontend/dist
# Create non-root user
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
# Expose ports (7860 is required for Hugging Face Spaces, 8000 for Render, 8501 for Streamlit)
EXPOSE 7860 8000 8501
# Set default port to 7860 for Hugging Face Spaces
# Render will override this environment variable at runtime
ENV PORT=7860
ENV NOVA_LOW_MEMORY=false
ENV NOVA_FORCE_VECTOR_ARTIFACTS=true
ENV NOVA_EAGER_MODEL_DOWNLOAD=true
ENV NOVA_REFRESH_PIPELINE_MANIFEST=true
ENV NOVA_HEALTH_LOAD_RECOMMENDER=false
ENV NOVA_BACKGROUND_RECOMMENDER_WARMUP=true
ENV NOVA_ASYNC_EVALUATION_CACHE=true
ENV NOVA_PRECOMPUTE_SEMANTIC_BENCHMARK=false
ENV NOVA_PRECOMPUTE_RECOMMENDATION_BENCHMARK=false
ENV NOVA_RECOMMENDER_CIRCUIT_FAILURE_THRESHOLD=3
ENV NOVA_RECOMMENDER_CIRCUIT_OPEN_SECONDS=60
ENV NOVA_RECOMMENDER_CACHE_ENABLED=true
ENV NOVA_RECOMMENDER_CACHE_READS=true
ENV NOVA_RECOMMENDER_CACHE_MAX_ENTRIES=512
ENV NOVA_RECOMMENDER_CACHE_TTL_SECONDS=300
ENV NOVA_RECOMMENDER_STALE_CACHE_TTL_SECONDS=21600
ENV NOVA_RECOMMENDER_DISTRIBUTED_CACHE_ENABLED=true
ENV NOVA_RECOMMENDER_DISTRIBUTED_CACHE_TIMEOUT_SECONDS=1.5
ENV NOVA_SLO_WINDOW_SECONDS=3600
ENV NOVA_SLO_MIN_REQUESTS=5
ENV NOVA_SLO_MIN_ROUTE_REQUESTS=20
ENV NOVA_SLO_LATENCY_P95_MS=2500
ENV NOVA_SLO_ERROR_RATE=0.03
ENV NOVA_SLO_MAX_EVENTS=5000
ENV NOVA_SLO_EXCLUDED_ROUTE_PREFIXES=/docs,/redoc,/openapi.json,/favicon.ico,/v1/artifacts,/v1/diagnostics,/v1/evaluation,/v1/platform/readiness
ENV NOVA_SLO_ROUTE_LATENCY_BUDGETS=/:1000,/health:1000,/v1/frontends/status:3000,/v1/platform/slo:1000,/v1/search:2500,/v1/recommendations/id/{movie_id}:25000
ENV NOVA_FRONTEND_PRIORITY=github_pages,react,streamlit
ENV NOVA_FRONTEND_STREAMLIT_URL=https://a-movie-recommendation-system.streamlit.app
ENV NOVA_FRONTEND_REACT_URL=/ui/
ENV NOVA_FRONTEND_PAGES_URL=https://movie-recommendation-system-6bm.pages.dev
ENV NOVA_FRONTEND_HEALTH_TIMEOUT_SECONDS=2.5
ENV NOVA_FRONTEND_HEALTH_CACHE_SECONDS=30
# Default command: run backend API.
CMD ["sh", "-c", "uvicorn backend.main:app --host 0.0.0.0 --port $PORT"]
ENV NOVA_APP_COMMIT=f4baf923f7fb1a50850f7eedab23421bcb6df487
ENV NOVA_APP_COMMIT=9a1db81cd9d34eff7b8e9c551e53d0ce51e472aa
ENV NOVA_APP_COMMIT=5136c711de4d7d53e1f0473cd9723aa666f6afe4
ENV NOVA_APP_COMMIT=e322b8f6e5820b07dcd4263ebe1dd6935fd51fc5
ENV NOVA_APP_COMMIT=78a33d20d52a6b5ab1f3ebce24d0578bf3c3a47f
ENV NOVA_APP_COMMIT=062a56b52d2912c7c4560e3699b56d517c83b8de
ENV NOVA_APP_COMMIT=c3def473e19ce620beabe18621fdf5be84a884a7
ENV NOVA_APP_COMMIT=d4fa96c13b9404a74cb4b80a301c7f0975cf229b
ENV NOVA_APP_COMMIT=ea81ba0f20f185588b6d6f6d9ad122f2ffd3dce2
ENV NOVA_APP_COMMIT=2a057d80cee0fde89ccddac8b5c2c1e97891a15e