|
| 1 | +# ============================================================================= |
1 | 2 | # Stage 1: Build Vue.js frontend |
| 3 | +# ============================================================================= |
2 | 4 | FROM node:20-alpine AS frontend-builder |
3 | 5 | WORKDIR /app/frontend |
4 | 6 | COPY frontend/package*.json ./ |
5 | 7 | RUN npm ci |
6 | 8 | COPY frontend/ ./ |
7 | 9 | RUN npm run build |
8 | 10 |
|
9 | | -# Stage 2: Python backend + compiled frontend |
10 | | -FROM python:3.11-slim AS runtime |
| 11 | +# ============================================================================= |
| 12 | +# Stage 2: Build gpredomicspy (Rust → Python native module) |
| 13 | +# ============================================================================= |
| 14 | +FROM python:3.11-slim AS rust-builder |
11 | 15 |
|
12 | | -# Install Rust toolchain for building gpredomicspy |
13 | 16 | RUN apt-get update && apt-get install -y --no-install-recommends \ |
14 | | - build-essential curl && \ |
| 17 | + build-essential curl git pkg-config libssl-dev && \ |
15 | 18 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \ |
16 | 19 | rm -rf /var/lib/apt/lists/* |
17 | 20 | ENV PATH="/root/.cargo/bin:${PATH}" |
18 | 21 |
|
| 22 | +RUN pip install --no-cache-dir maturin |
| 23 | + |
| 24 | +WORKDIR /build |
| 25 | +COPY gpredomicspy/ ./gpredomicspy/ |
| 26 | +RUN cd gpredomicspy && maturin build --release --out /build/wheels |
| 27 | + |
| 28 | +# ============================================================================= |
| 29 | +# Stage 3: Runtime — Python backend + frontend + gpredomicspy wheel |
| 30 | +# ============================================================================= |
| 31 | +FROM python:3.11-slim AS runtime |
| 32 | + |
| 33 | +RUN apt-get update && apt-get install -y --no-install-recommends \ |
| 34 | + libgomp1 && \ |
| 35 | + rm -rf /var/lib/apt/lists/* |
| 36 | + |
19 | 37 | WORKDIR /app |
20 | 38 |
|
21 | | -# Install Python dependencies |
22 | | -COPY backend/pyproject.toml backend/ |
23 | | -RUN pip install --no-cache-dir -e backend/ |
| 39 | +# Install gpredomicspy wheel (built in stage 2) |
| 40 | +COPY --from=rust-builder /build/wheels/*.whl /tmp/wheels/ |
| 41 | +RUN pip install --no-cache-dir /tmp/wheels/*.whl && rm -rf /tmp/wheels |
24 | 42 |
|
25 | | -# Install gpredomicspy from source (requires Rust) |
26 | | -# For now, this is optional — the app works in mock mode without it |
27 | | -# COPY gpredomicspy/ gpredomicspy/ |
28 | | -# RUN cd gpredomicspy && pip install maturin && maturin develop --release |
| 43 | +# Install Python backend dependencies |
| 44 | +COPY backend/pyproject.toml backend/ |
| 45 | +RUN pip install --no-cache-dir backend/ |
29 | 46 |
|
30 | 47 | # Copy backend code |
31 | 48 | COPY backend/ backend/ |
32 | 49 |
|
33 | | -# Copy built frontend |
| 50 | +# Copy built frontend into static directory |
34 | 51 | COPY --from=frontend-builder /app/frontend/dist backend/static/ |
35 | 52 |
|
36 | 53 | # Copy sample data |
37 | 54 | COPY data/sample/ data/sample/ |
38 | 55 |
|
| 56 | +# Create directories for runtime data |
| 57 | +RUN mkdir -p data/uploads data/projects |
| 58 | + |
39 | 59 | EXPOSE 8000 |
40 | 60 |
|
| 61 | +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \ |
| 62 | + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 |
| 63 | + |
41 | 64 | CMD ["uvicorn", "backend.app.main:app", "--host", "0.0.0.0", "--port", "8000"] |
0 commit comments