|
|
|
|
|
FROM node:20-bullseye AS fe |
|
|
WORKDIR /app/frontend |
|
|
COPY frontend/package*.json ./ |
|
|
RUN npm ci |
|
|
COPY frontend/ ./ |
|
|
RUN npm run build |
|
|
|
|
|
|
|
|
FROM python:3.11-slim AS be |
|
|
ENV PIP_NO_CACHE_DIR=1 PYTHONUNBUFFERED=1 PIP_PREFER_BINARY=1 |
|
|
WORKDIR /app |
|
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
|
build-essential gcc g++ gfortran make pkg-config \ |
|
|
libopenblas-dev liblapack-dev git \ |
|
|
&& rm -rf /var/lib/apt/lists/* |
|
|
|
|
|
RUN python -m venv /opt/venv |
|
|
ENV PATH="/opt/venv/bin:${PATH}" |
|
|
|
|
|
RUN python -m pip install --upgrade pip setuptools wheel |
|
|
|
|
|
RUN pip install --index-url https://download.pytorch.org/whl/cpu "torch==2.3.1" |
|
|
|
|
|
COPY backend/requirements.txt ./backend/requirements.txt |
|
|
RUN sed -i 's/^[Tt]orch[[:space:]=<>!].*/# torch pinned separately (CPU)/' backend/requirements.txt || true |
|
|
|
|
|
RUN pip install --only-binary=:all: blis || echo "Precompiled blis not available" |
|
|
RUN pip install -r backend/requirements.txt || pip install -r backend/requirements.txt --no-deps |
|
|
|
|
|
RUN pip install --no-cache-dir gunicorn |
|
|
|
|
|
COPY backend/ ./backend/ |
|
|
|
|
|
|
|
|
FROM python:3.11-slim AS runtime |
|
|
ENV PYTHONUNBUFFERED=1 PIP_NO_CACHE_DIR=1 PORT=7860 \ |
|
|
PATH="/opt/venv/bin:${PATH}" |
|
|
|
|
|
WORKDIR /app |
|
|
|
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
|
nginx supervisor ca-certificates \ |
|
|
libgomp1 libopenblas0 \ |
|
|
&& rm -rf /var/lib/apt/lists/* |
|
|
|
|
|
COPY --from=fe /app/frontend/dist /usr/share/nginx/html |
|
|
|
|
|
COPY --from=be /opt/venv /opt/venv |
|
|
|
|
|
COPY --from=be /app/backend /app/backend |
|
|
|
|
|
COPY nginx.conf.template /etc/nginx/nginx.conf |
|
|
|
|
|
RUN set -eux; \ |
|
|
sed -ri 's/^\s*user\s+[^;]+;//g' /etc/nginx/nginx.conf || true; \ |
|
|
if grep -qE '^\s*pid\s+' /etc/nginx/nginx.conf; then \ |
|
|
sed -ri 's|^\s*pid\s+[^;]+;|pid /tmp/nginx.pid;|' /etc/nginx/nginx.conf; \ |
|
|
else \ |
|
|
sed -ri '1i pid /tmp/nginx.pid;' /etc/nginx/nginx.conf; \ |
|
|
fi |
|
|
|
|
|
RUN mkdir -p /etc/supervisor/conf.d && \ |
|
|
printf "[program:api]\n\ |
|
|
command=gunicorn --workers 2 --threads 8 --timeout 0 --chdir /app/backend -b 0.0.0.0:5001 server:app\n\ |
|
|
priority=10\nautostart=true\nautorestart=true\n\ |
|
|
stdout_logfile=/dev/stdout\nstderr_logfile=/dev/stderr\n\ |
|
|
stdout_logfile_maxbytes=0\nstderr_logfile_maxbytes=0\n\n\ |
|
|
[program:nginx]\n\ |
|
|
command=nginx -g \"daemon off;\"\n\ |
|
|
priority=20\nautostart=true\nautorestart=true\n\ |
|
|
stdout_logfile=/dev/stdout\nstderr_logfile=/dev/stderr\n\ |
|
|
stdout_logfile_maxbytes=0\nstderr_logfile_maxbytes=0\n\n\ |
|
|
[supervisord]\n\ |
|
|
logfile=/dev/stdout\nlogfile_maxbytes=0\nnodaemon=true\n" \ |
|
|
> /etc/supervisor/conf.d/app.conf |
|
|
|
|
|
EXPOSE 7860 |
|
|
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/app.conf"] |
|
|
|