# Stage 1: build the React frontend FROM node:20-alpine AS frontend-build WORKDIR /build/frontend COPY web_ui/frontend/package*.json ./ RUN npm ci COPY web_ui/frontend/ ./ RUN npm run build # Stage 2: production image (Hugging Face Spaces) FROM python:3.13-slim # nginx for serving static assets and proxying /api + /ws to uvicorn RUN apt-get update \ && apt-get install -y --no-install-recommends nginx \ && rm -rf /var/lib/apt/lists/* # Non-root user (HF Spaces runs as uid 1000) RUN useradd -m -u 1000 appuser # Python dependencies (gMAS + web UI) WORKDIR /app COPY pyproject.toml ./ COPY src/ ./src/ RUN pip install --no-cache-dir ".[webui]" WORKDIR /app/web_ui # Backend application code COPY web_ui/backend/ ./backend/ # Built frontend assets COPY --from=frontend-build /build/frontend/dist /app/web_ui/frontend/dist # nginx config (non-root compatible) COPY web_ui/nginx.conf /etc/nginx/sites-available/default # Entrypoint COPY web_ui/docker-entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh # Make writable dirs for non-root nginx and app data RUN mkdir -p /app/data /tmp/nginx \ && chown -R appuser:appuser /app /tmp/nginx \ && chown -R appuser:appuser /var/lib/nginx /var/log/nginx # Runtime environment ENV GMAS_GMAS_SRC_PATH=/app/src ENV GMAS_DATA_DIR=/app/data ENV PYTHONPATH=/app/web_ui:/app/src USER appuser EXPOSE 7860 ENTRYPOINT ["/entrypoint.sh"]