# Playwright's official image ships Chromium + all system deps prematched to the # playwright pip version below — avoids hand-rolling apt/xvfb setup for headless Chrome. FROM mcr.microsoft.com/playwright/python:v1.44.0-jammy WORKDIR /app # Fetch + unpack the Keyword Surfer extension at build time. Non-fatal if it fails — # modules/keywords.py falls back to Autocomplete/pytrends/LLM estimates at runtime. COPY scripts/fetch_extension.py ./scripts/fetch_extension.py RUN pip install --no-cache-dir httpx && \ python scripts/fetch_extension.py --out /app/extension || true # CPU-only torch, installed BEFORE requirements.txt so sentence-transformers' # transitive "torch" dependency is already satisfied by this build instead of # pulling PyPI's default CUDA-enabled build (~2GB of unused nvidia-cu* wheels # for a GPU this Space's default CPU hardware doesn't have — the RAG embedder # here is a small model doing a handful of queries per request, CPU is fine). RUN pip install --no-cache-dir torch --index-url https://download.pytorch.org/whl/cpu COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . COPY modules/ ./modules/ COPY data/ ./data/ ENV GRADIO_SERVER_NAME=0.0.0.0 ENV GRADIO_SERVER_PORT=7860 # Without this, stdout is block-buffered in a non-TTY container: print() # output (our own startup/progress logs) sits unflushed while stderr-based # output (tqdm progress bars) appears immediately, making logs look stuck. ENV PYTHONUNBUFFERED=1 EXPOSE 7860 # rag_index/ is NOT copied at build time — it's 2.3GB (over the free-tier 1GB # private-repo LFS limit baked into an image would mean re-transferring it on # every build). Instead modules/rag.py downloads it at container startup from # a separate private HF Dataset repo, via RAG_DATASET_ID + RAG_DATASET_TOKEN. # # Required as Space secrets in Settings > Repository secrets, NOT here and NOT # via a committed .env file: # RAG_DATASET_ID e.g. vivekchakraverty/digital-marketer-rag-index # RAG_DATASET_TOKEN read access to that dataset repo # GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET, # GOOGLE_ADS_REFRESH_TOKEN, GOOGLE_ADS_LOGIN_CUSTOMER_ID (optional tier-1 # keyword data; modules/keywords.py falls back to tier 2 if unset) # HF Spaces injects Repository secrets as environment variables at container # runtime automatically — no Dockerfile/ENV changes needed to receive them. CMD ["python", "app.py"]