# ============================================ # Base stage for shared configuration # ============================================ FROM python:3.10-slim-bookworm AS base # Configure build environment with optimized settings ENV NODE_OPTIONS="--max_old_space_size=2048" \ NEXT_TELEMETRY_DISABLED=1 \ NODE_ENV=production \ PYTHONDONTWRITEBYTECODE=1 \ TZ=UTC \ STORAGE_DIR=/storage # Install base dependencies RUN apt-get update && \ apt-get install -y --no-install-recommends \ tzdata git curl && \ rm -f /etc/localtime && \ ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \ echo $TZ > /etc/timezone # ============================================ # Web builder stage - optimized # ============================================ FROM base AS web-builder # Install Node.js and build tools RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get update && \ apt-get install -y nodejs && \ npm install -g yarn WORKDIR /app # Copy web directory first COPY web/ web/ WORKDIR /app/web # Install dependencies and build RUN yarn install --frozen-lockfile && \ yarn add --dev autoprefixer postcss tailwindcss code-inspector-plugin && \ NEXT_TELEMETRY_DISABLED=1 yarn build && \ mkdir -p .next/standalone && \ cp -r .next/static .next/standalone/.next/ && \ cp -r public .next/standalone/ && \ yarn cache clean # ============================================ # Python builder stage - optimized # ============================================ FROM base AS python-builder # Install build dependencies RUN apt-get install -y --no-install-recommends \ gcc g++ libc-dev libffi-dev \ libgmp-dev libmpfr-dev libmpc-dev \ libssl-dev WORKDIR /app # Copy api directory COPY api/ api/ WORKDIR /app/api # Install core dependencies first RUN pip install --no-cache-dir \ poetry==1.8.3 \ gunicorn \ gevent \ grpcio \ pydantic-settings \ protobuf \ grpcio-tools \ flask \ flask-cors \ flask-sqlalchemy \ flask-migrate \ flask-login \ flask-restful \ flask-limiter \ flask-caching \ flask-jwt-extended \ flask-socketio \ PyYAML \ celery \ redis \ psycopg2-binary \ sqlalchemy \ alembic \ pyjwt \ requests \ numpy \ pandas \ python-dotenv \ pycryptodome \ cryptography \ bcrypt \ python-jose[cryptography] \ passlib \ python-multipart \ gmpy2 && \ poetry config virtualenvs.create false && \ poetry install --no-dev --no-interaction --no-ansi # ============================================ # Final stage - minimal runtime # ============================================ FROM base # Create non-root user and storage directory RUN useradd -m -u 1000 user && \ mkdir -p /storage/files /storage/cache /storage/logs && \ chown -R user:user /storage # Install runtime dependencies RUN apt-get install -y --no-install-recommends \ nodejs npm libgmp-dev libmpfr-dev libmpc-dev libssl-dev && \ pip install --no-cache-dir \ gunicorn \ gevent \ grpcio \ pydantic-settings \ protobuf \ grpcio-tools \ flask \ flask-cors \ flask-sqlalchemy \ flask-migrate \ flask-login \ flask-restful \ flask-limiter \ flask-caching \ flask-jwt-extended \ flask-socketio \ PyYAML \ celery \ redis \ psycopg2-binary \ sqlalchemy \ alembic \ pyjwt \ requests \ numpy \ pandas \ python-dotenv \ pycryptodome \ cryptography \ bcrypt \ python-jose[cryptography] \ passlib \ python-multipart \ gmpy2 \ nltk && \ python -m nltk.downloader punkt averaged_perceptron_tagger # Set up directory structure WORKDIR /app RUN mkdir -p api web && chown -R user:user /app # Copy Python environment and files COPY --from=python-builder --chown=user /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages COPY --chown=user api/ /app/api/ # Copy Next.js files with explicit directory creation RUN mkdir -p /app/web/.next/standalone /app/web/.next/static COPY --from=web-builder --chown=user /app/web/.next/standalone /app/web/.next/standalone COPY --from=web-builder --chown=user /app/web/.next/static /app/web/.next/static COPY --from=web-builder --chown=user /app/web/public /app/web/public # Set environment variables for HF Spaces compatibility ENV FLASK_APP=app.py \ EDITION=SELF_HOSTED \ DEPLOY_ENV=PRODUCTION \ CONSOLE_API_URL=http://127.0.0.1:7860 \ CONSOLE_WEB_URL=http://127.0.0.1:3000 \ SERVICE_API_URL=http://127.0.0.1:7860 \ APP_WEB_URL=http://127.0.0.1:3000 \ PYTHONPATH=/app/api \ PATH="/usr/local/bin:${PATH}" \ STORAGE_DIR=/storage # Copy entrypoint script COPY docker/entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh # Switch to non-root user USER user # HF Spaces uses port 7860 EXPOSE 7860 3000 # Set up storage volumes VOLUME ["/storage/files", "/storage/cache", "/storage/logs"] WORKDIR /app CMD ["./entrypoint.sh"]