Spaces:
Sleeping
Sleeping
File size: 4,815 Bytes
945ae45 53c3899 945ae45 53c3899 945ae45 53c3899 945ae45 53c3899 945ae45 9e9393d 7759bfb 355c4d1 65ea09d e2b8b62 65ea09d 7759bfb 8155d78 99c9c71 53c3899 99c9c71 53c3899 e42000f 53c3899 945ae45 53c3899 945ae45 a008453 945ae45 53c3899 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | FROM python:3.11-slim
# System deps for Playwright + Node.js + git
RUN apt-get update && apt-get install -y \
wget curl gnupg ca-certificates git \
libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
libgbm1 libasound2 libxshmfence1 libx11-xcb1 \
libxcb-dri3-0 libpango-1.0-0 libcairo2 libfontconfig1 \
fonts-liberation libappindicator3-1 xdg-utils \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20 LTS (needed to run ever-jobs NestJS API)
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user (HF Spaces requirement)
RUN useradd -m -u 1000 user
USER user
ENV HOME=/home/user PATH=/home/user/.local/bin:$PATH
WORKDIR /app
# Install Python deps (separate layer β cached unless requirements.txt changes)
COPY --chown=user requirements.txt .
RUN pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir -r requirements.txt
# Install Playwright Chromium browser
RUN playwright install chromium
# Install Scrapling's stealth browser (Camoufox) + fetcher deps for the
# anti-block fetch layer. Non-fatal: if the Camoufox download hiccups, the
# lightweight HTTP TLS-impersonation path (Fetcher) and the requests fallback
# still work β only the Cloudflare-bypass StealthyFetcher would be unavailable.
RUN (scrapling install || python -m scrapling install || true)
# Install Tectonic (self-contained LaTeX engine) for compiling user resume
# LaTeX β PDF. Pin a specific MUSL-STATIC release: the rolling drop-sh installer
# shipped a glibc build that crashed at COMPILE time with "free(): invalid
# pointer" (a glibc heap abort β note it ran `tectonic --version` fine, so a
# version gate did not catch it). The musl static binary does not link glibc, so
# it cannot hit that class of crash and is maximally portable in the container.
ENV TECTONIC_CACHE_DIR=/home/user/.cache/tectonic
RUN mkdir -p /home/user/.local/bin /home/user/.cache/tectonic \
&& cd /tmp \
&& curl --proto '=https' --tlsv1.2 -fsSL -o tectonic.tar.gz \
https://github.com/tectonic-typesetting/tectonic/releases/download/tectonic%400.16.9/tectonic-0.16.9-x86_64-unknown-linux-musl.tar.gz \
&& tar -xzf tectonic.tar.gz \
&& mv tectonic /home/user/.local/bin/tectonic \
&& chmod +x /home/user/.local/bin/tectonic \
&& rm -f tectonic.tar.gz \
&& tectonic --version
# Pre-warm the bundle cache by compiling the SANITIZED resume β the exact source
# the server compiles at runtime (_sanitize_for_tectonic strips fontawesome5's OTF
# loader, which SEGFAULTS Tectonic's XeTeX, and the FiraMono font loader). This
# caches every package/font the real compile uses AND proves the sanitized template
# actually compiles at BUILD time (grep the build log for "TECTONIC_REAL_WARMUP").
# Build gate is intentionally non-fatal so a transient warmup hiccup never bricks
# the Space; the OK/FAILED marker + log tail make the outcome visible.
COPY --chown=user assets/default_resume.tectonic.tex /tmp/warm-resume.tex
RUN (tectonic --outdir /tmp /tmp/warm-resume.tex \
&& echo "TECTONIC_REAL_WARMUP_OK" \
|| (echo "TECTONIC_REAL_WARMUP_FAILED β full log follows:" \
&& cat /tmp/warm-resume.log 2>/dev/null | tail -80 || true)) \
&& rm -f /tmp/warm-resume.pdf
# Hard build gate: fail the image build if the Tectonic binary is missing/broken
# (so we never silently ship a no-LaTeX-engine image β R16).
RUN tectonic --version
# Clone ever-jobs and install Node deps (separate layer β cached unless repo changes)
# vendor/ is in .dockerignore so it never comes from the build context
# nest-cli.json forces webpack which isn't installed; ts-node (nest start) is used at runtime instead
RUN git clone https://github.com/ever-jobs/ever-jobs.git vendor/ever-jobs --depth=1 \
&& cd vendor/ever-jobs \
&& npm install --legacy-peer-deps \
&& sed -i 's/"webpack": true/"webpack": false/g' nest-cli.json
# Copy app code (this layer re-runs on every code change, which is expected)
COPY --chown=user . .
# Create required runtime directories
RUN mkdir -p data/resume data/output/resumes data/output/reports \
data/research_cache data/logs data/output/run_history
# Make startup script executable
RUN chmod +x start.sh
# Expose Streamlit port
EXPOSE 7860
# Only keep non-conflicting Streamlit env vars.
# STREAMLIT_SERVER_PORT and STREAMLIT_SERVER_ADDRESS are intentionally omitted:
# they would conflict with the proxy architecture where api_server.py runs
# uvicorn on 7860 and Streamlit is started on 127.0.0.1:8501 via CLI args.
ENV STREAMLIT_SERVER_HEADLESS=true \
STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
CMD ["./start.sh"]
|