1+ # Multi-stage Dockerfile for React frontend with Python backend support using UV
2+
3+ # Stage 1: Node build environment for React
4+ FROM node:18-alpine AS frontend-builder
5+
6+ WORKDIR /app/frontend
7+
8+ # Copy package files first for better caching
9+ COPY src/frontend_react/package*.json ./
10+
11+ # Install dependencies
12+ RUN npm ci --silent
13+
14+ # Copy source files
15+ COPY src/frontend_react/ ./
16+
17+ # Build the React app
18+ RUN npm run build
19+
20+ # Stage 2: Python build environment with UV
21+ FROM mcr.microsoft.com/devcontainers/python:3.11-bullseye AS python-builder
22+
23+ # Copy UV from official image
24+ COPY --from=ghcr.io/astral-sh/uv:0.6.3 /uv /uvx /bin/
25+
26+ # Setup UV environment variables
27+ ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
28+
29+ WORKDIR /app
30+
31+ # Copy Python project definition files
32+ COPY src/frontend_react/pyproject.toml src/frontend_react/uv.lock* ./
33+
34+ # Install Python dependencies using UV
35+ RUN --mount=type=cache,target=/root/.cache/uv \
36+ uv pip install --system -r <(uv pip freeze --requirement pyproject.toml)
37+
38+ # Stage 3: Final production image
39+ FROM python:3.11-slim-bullseye
40+
41+ # Set production environment
42+ ENV NODE_ENV=production \
43+ PYTHONDONTWRITEBYTECODE=1 \
44+ PYTHONUNBUFFERED=1 \
45+ PATH="/app/venv/bin:$PATH"
46+
47+ WORKDIR /app
48+
49+ # Create a non-root user for security
50+ RUN adduser --disabled-password --gecos "" appuser && \
51+ mkdir -p /app/static && \
52+ chown -R appuser:appuser /app
53+
54+ # Copy Python dependencies from builder
55+ COPY --from=python-builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
56+ COPY --from=python-builder /usr/local/bin /usr/local/bin
57+
58+ # Copy React build artifacts
59+ COPY --from=frontend-builder --chown=appuser:appuser /app/frontend/build /app/static
60+
61+ # Copy Python application code
62+ COPY --chown=appuser:appuser src/frontend_react/*.py /app/
63+
64+ # Create log directory with correct permissions
65+ RUN mkdir -p /app/logs && chown -R appuser:appuser /app/logs
66+
67+ # Use non-root user for security
68+ USER appuser
69+
70+ # Expose port
71+ EXPOSE 3000
72+
73+ # Health check
74+ HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
75+ CMD curl -f http://localhost:3000/health || exit 1
76+
77+ # Run the application with uvicorn
78+ CMD ["uvicorn" , "server:app" , "--host" , "0.0.0.0" , "--port" , "3000" , "--log-config" , "log_config.json" ]
0 commit comments