grantforge-api / Dockerfile
GrantForge Bot
Deploy to Hugging Face
afd56bc
# GrantForge AI β€” Multi-stage Docker build
# Backend: FastAPI + LangGraph | Frontend: Vite React
# ──────────────────────────────────────────────────────────────────
# STAGE 1: Frontend build
# ──────────────────────────────────────────────────────────────────
FROM node:20-slim AS frontend-builder
WORKDIR /app/frontend
COPY frontend-react/package*.json ./
RUN rm -f package-lock.json && npm install
COPY frontend-react/ ./
RUN npm run build
# Artefakt: /app/frontend/dist/
# ──────────────────────────────────────────────────────────────────
# STAGE 2: Python dependencies
# ──────────────────────────────────────────────────────────────────
FROM python:3.11.9-slim AS python-deps
WORKDIR /install
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq-dev gcc g++ libffi-dev libglib2.0-0 libpango-1.0-0 \
libpangocairo-1.0-0 libcairo2 libcairo2-dev pkg-config python3-dev \
&& rm -rf /var/lib/apt/lists/*
COPY backend/requirements.txt .
RUN pip install --no-cache-dir --prefix=/install/pkg -r requirements.txt && \
rm -rf /install/pkg/lib/python3.11/site-packages/pinecone_plugin_inference*
# ──────────────────────────────────────────────────────────────────
# STAGE 3: Runtime image
# ──────────────────────────────────────────────────────────────────
FROM python:3.11.9-slim AS runtime
WORKDIR /app
COPY --from=python-deps /install/pkg /usr/local
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 libglib2.0-0 libpango-1.0-0 libpangocairo-1.0-0 libcairo2 wget \
&& rm -rf /var/lib/apt/lists/*
COPY backend/ ./backend/
COPY --from=frontend-builder /app/frontend/dist ./static/
RUN mkdir -p /app/backend/assets && \
wget -qO /app/backend/assets/Roboto-Regular.ttf "https://github.com/googlefonts/roboto/raw/main/src/hinted/Roboto-Regular.ttf" && \
wget -qO /app/backend/assets/Roboto-Bold.ttf "https://github.com/googlefonts/roboto/raw/main/src/hinted/Roboto-Bold.ttf"
RUN mkdir -p /app/backend/cache
RUN useradd -m -u 1001 appuser && chown -R appuser:appuser /app
USER appuser
WORKDIR /app/backend
EXPOSE 7860
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/api/health')"
CMD ["gunicorn", "server:app", \
"--worker-class", "uvicorn.workers.UvicornWorker", \
"--workers", "2", \
"--bind", "0.0.0.0:7860", \
"--timeout", "120", \
"--access-logfile", "-"]