| ############################### | |
| # 1) βββ Python builder βββ | |
| ############################### | |
| FROM python:3.11-slim AS builder | |
| WORKDIR /app | |
| RUN apt-get update && apt-get install -y --no-install-recommends gcc g++ git curl wget \ | |
| && rm -rf /var/lib/apt/lists/* | |
| COPY requirements.txt . | |
| RUN pip wheel --no-cache-dir --wheel-dir=/app/wheels -r requirements.txt | |
| ############################### | |
| # 2) βββ Runtime image βββ | |
| ############################### | |
| FROM python:3.11-slim | |
| WORKDIR /app | |
| # OS runtime deps (minimal for memory optimization) | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| libgomp1 \ | |
| nginx \ | |
| supervisor \ | |
| && rm -rf /var/lib/apt/lists/* \ | |
| && apt-get clean | |
| # Python deps | |
| COPY --from=builder /app/wheels /wheels | |
| COPY requirements.txt . | |
| # Install Python dependencies (with cleanup for memory optimization) | |
| RUN pip install --no-cache-dir --no-index --find-links=/wheels -r requirements.txt \ | |
| && rm -rf /wheels \ | |
| && pip cache purge | |
| # Install Playwright system dependencies and browsers | |
| # && python -m playwright install-deps \ | |
| # && python -m playwright install chromium firefox webkit | |
| # Create necessary directories with proper permissions for root | |
| RUN mkdir -p /data/advisorai-data/archive \ | |
| && mkdir -p /data/advisorai-data/features \ | |
| && mkdir -p /data/advisorai-data/temp \ | |
| && mkdir -p /data/advisorai-data/train \ | |
| && mkdir -p /data/advisorai-data/warehouse \ | |
| && mkdir -p /data/alpaca/archive \ | |
| && mkdir -p /data/alpaca/features \ | |
| && mkdir -p /data/alpaca/temp \ | |
| && mkdir -p /data/alpaca/train \ | |
| && mkdir -p /data/crypto-bubbles/archive \ | |
| && mkdir -p /data/crypto-bubbles/features \ | |
| && mkdir -p /data/crypto-bubbles/temp \ | |
| && mkdir -p /data/crypto-bubbles/train \ | |
| && mkdir -p /data/finnhub/archive \ | |
| && mkdir -p /data/finnhub/features \ | |
| && mkdir -p /data/finnhub/temp \ | |
| && mkdir -p /data/finnhub/train \ | |
| && mkdir -p /data/finviz/archive \ | |
| && mkdir -p /data/finviz/features \ | |
| && mkdir -p /data/finviz/temp \ | |
| && mkdir -p /data/finviz/train \ | |
| && mkdir -p /data/marketaux/archive \ | |
| && mkdir -p /data/marketaux/features \ | |
| && mkdir -p /data/marketaux/temp \ | |
| && mkdir -p /data/marketaux/train \ | |
| && mkdir -p /data/merged/archive \ | |
| && mkdir -p /data/merged/features \ | |
| && mkdir -p /data/merged/temp \ | |
| && mkdir -p /data/merged/train \ | |
| && mkdir -p /data/merged/raw \ | |
| && mkdir -p /data/logs \ | |
| && mkdir -p /data/nltk_data \ | |
| && mkdir -p /tmp/nginx/body \ | |
| && mkdir -p /tmp/nginx/proxy \ | |
| && mkdir -p /tmp/nginx/fastcgi \ | |
| && chmod -R 777 /data /tmp/nginx | |
| # βββ Application code βββ | |
| COPY . . | |
| # Set executable permissions for entrypoint | |
| RUN chmod +x /app/deployment/entrypoint.sh /app/deployment/gradio_entrypoint.sh | |
| # PYTHONPATH for FastAPI | |
| ENV PYTHONPATH=/app:/app/src:/app/src/api:/app/src/data_cloud:/app/src/fetchers:/app/src/merge | |
| # Nginx config | |
| RUN rm -f /etc/nginx/conf.d/default.conf | |
| COPY deployment/nginx.conf /etc/nginx/conf.d/app.conf | |
| COPY deployment/nginx.main.conf /etc/nginx/nginx.conf | |
| # Set resource limits for memory optimization (512MB limit) | |
| ENV PYTHONUNBUFFERED=1 | |
| ENV PYTHONIOENCODING=utf-8 | |
| ENV MAX_MEMORY_MB=450 | |
| ENV MALLOC_TRIM_THRESHOLD_=100000 | |
| ENV MALLOC_MMAP_THRESHOLD_=131072 | |
| ENV PYTHONDONTWRITEBYTECODE=1 | |
| ENV PYTHONHASHSEED=random | |
| ENV NLTK_DATA=/data/nltk_data | |
| # Supervisord config | |
| COPY deployment/supervisord.conf /etc/supervisord.conf | |
| ENTRYPOINT ["/app/deployment/gradio_entrypoint.sh"] | |
| # Ports | |
| EXPOSE 80 7860 | |
| CMD ["supervisord", "-c", "/etc/supervisord.conf"] |