Spaces:
Running on RTX PRO 6000
Running on RTX PRO 6000
Download Dockerfile from nvidia/simready-central: direct link, hf CLI and curl.
- Browser
- Download file 28.4 kB
-
https://huggingface.co/spaces/nvidia/simready-central/resolve/main/Dockerfile
- Command line
-
hf download hf://spaces/nvidia/simready-central/Dockerfile
-
curl -L -o Dockerfile https://huggingface.co/spaces/nvidia/simready-central/resolve/main/Dockerfile
28.4 kB
| # deploy: 20261020-a3cb7f2-captions (simready-assets) | |
| # GPU variant of the single-container MVP image for Hugging Face Spaces | |
| # (Docker SDK): everything docker/Dockerfile.hf-space has (OpenSearch + Neo4j | |
| # + Redis + deepsearch-api + asset-graph-service + nginx under supervisord), | |
| # plus a *local* siglip2-triton process instead of routing SigLIP2 embeddings | |
| # to NVCF β see docs/development.md#hf-space-design-notes | |
| # for the decisions behind this file. Meant to be deployed to an HF Space running | |
| # on a GPU hardware tier (T4 medium β see pipeline/hf_space.py's | |
| # request_space_hardware call for the gpu variant); docker/Dockerfile.hf-space | |
| # remains the free/cpu-basic, NVCF-backed variant β this is an additional | |
| # deploy target, not a replacement (`SIGLIP2_BACKEND=nvcf` is unaffected). | |
| # | |
| # Builds the Triton half of this image the same way | |
| # ../usdsearch/docker/Dockerfile.siglip2-triton does β FROM the bare, public | |
| # nvcr.io/nvidia/tritonserver image, model_repo/ COPYed in from | |
| # docker/hf-space/siglip2-model/ (vendored into *this* repo by | |
| # scripts/extract_siglip2_model.sh, since HF's remote builder can reach | |
| # neither ../usdsearch nor any private registry) β rather than FROM the | |
| # prepackaged nvcr.io/nvidia/usdsearch/siglip2-triton image an earlier | |
| # revision of this file used. Verified live why that prepackaged image was | |
| # dropped: its published 1.4.0 tag bakes **FP32** weights (vision 4.4 GB + | |
| # text 2.7 GB, inspected inside a pulled copy) β at this model's baked | |
| # `instance_group: 2`, that's ~14 GB of resident GPU weight memory alone, | |
| # and ~18 GB observed live in `nvidia-smi`, blowing past a T4's 16 GB VRAM. | |
| # ../usdsearch's *current* services/siglip2-triton/model_repo checkout is | |
| # already FP16-exported (vision 2.2 GB + text 1.4 GB β half the size, ~7 GB | |
| # at instance_group: 2, comfortably under 16 GB) but was never republished | |
| # under that NGC tag β vendoring this checkout's own model_repo directly | |
| # sidesteps waiting on a new publish. See | |
| # scripts/extract_siglip2_model.sh's own header for the full mechanism. | |
| # | |
| # nvcr.io/nvidia/tritonserver itself (the base, not the prepackaged image) | |
| # is on the same *public* NGC catalog path already verified live this | |
| # project's other public pulls (opensearchproject/opensearch, neo4j) use β | |
| # no credentials needed, so Hugging Face's own remote builder can pull it. | |
| # | |
| # VERIFIED LIVE on a real GPU (RTX 4090, local β not a T4, but same | |
| # execution path): full build, `docker run --gpus all`, all 6 Triton models | |
| # READY, OpenSearch/Neo4j restore from S3, deepsearch-api + asset-graph-service | |
| # healthy through nginx. GPU memory settled at ~10-11 GB (tritonserver | |
| # ~10.3 GB + a smaller deepsearch-api CUDA-context allocation) β comfortably | |
| # under a T4's 16 GB, confirming the FP32->FP16 switch actually fixed the | |
| # budget problem, not just on paper. A real `/v3/deepsearch/search` call | |
| # came back with genuine `search_type: text_to_vector` / | |
| # `field: siglip2-embedding` hits (query "a red chair" correctly ranked | |
| # office-chair assets top) β the local siglip2-triton round trip is real, | |
| # not just "the process started". LLM query parsing | |
| # (`/v3/deepsearch/llm_parse/query`) and VLM validation | |
| # (`/v3/deepsearch/vlm_validate/search_result`) were also exercised live | |
| # against the already-deployed NVCF Qwen endpoint | |
| # (config/pipeline.env.srp-staging-controlled's LLM_ENDPOINT_BASE_URL) with | |
| # $NVCF_GENAI_RUN_KEY as USDSEARCH_LLM_API_KEY β both returned real model | |
| # output (a structured filter parse; a logprob-based | |
| # `P(Yes)=... from first-token log-probs.` verdict), confirming this | |
| # variant's NVCF-backed LLM/VLM path works the same as the NVCF/cpu-basic | |
| # variant's. | |
| # 3.9.0 rather than the pipeline's 3.8.0: 3.8.0's netty-handler 4.2.16 | |
| # (GHSA-c4c3-7fpv-j4q5, Critical) and httpcore5 5.4 jars were flagged by the | |
| # nSpect container scan (2026-10-02). The Space bulk-loads the pipeline's | |
| # NDJSON (pipeline/restore.py) rather than restoring a snapshot, so the | |
| # versions don't need to match. Not named OPENSEARCH_VERSION: the jar patches | |
| # below are tied to this exact version, and the pipeline's own | |
| # OPENSEARCH_VERSION used to be passed through as a build-arg (and is still | |
| # set as a Variable on the existing Spaces, which HF would pass along). | |
| ARG HF_SPACE_OPENSEARCH_VERSION=3.9.0 | |
| # 5.26 (LTS) rather than the pipeline's 5.23: 5.23's bundled netty/jackson/ | |
| # jetty/shiro jars, APOC's json-smart and its JDK 17.0.12 were all flagged | |
| # High by the nSpect container scan (2026-10-02). Same major version, so the | |
| # pipeline's 5.23 dumps still load (verified locally). | |
| ARG NEO4J_VERSION=5.26.31-community | |
| ARG TRITONSERVER_BASE_IMAGE=nvcr.io/nvidia/tritonserver:26.05-py3 | |
| ARG PYTHON_IMAGE=python:3.12-bookworm | |
| FROM opensearchproject/opensearch:${HF_SPACE_OPENSEARCH_VERSION} AS opensearch-src | |
| FROM neo4j:${NEO4J_VERSION} AS neo4j-src | |
| FROM ${TRITONSERVER_BASE_IMAGE} | |
| WORKDIR /workspace | |
| RUN mkdir -p /models | |
| # Vendored model repo (see header comment) β ensembles, the Python-backend | |
| # tokenizer/preprocessing models, and the two ONNX encoders' *config.pbtxt* | |
| # only. The encoders' actual weight files (~3.6 GB combined β the ONNX | |
| # externa-data blobs under each encoder's own 1/ subdirectory) are | |
| # deliberately NOT baked here: a real `deploy-space-gpu` attempt 403'd with | |
| # "Repository storage limit reached (Max: 1 GB)" β HF Space git repos have a | |
| # default 1 GB storage quota, well under what baking these in needs. Instead | |
| # they're restored from the artifact S3 bucket at container startup | |
| # (pipeline/hf_space_seed.py --component=siglip2-model, run by | |
| # supervisord-gpu.conf's [program:siglip2-triton] before tritonserver | |
| # itself execs) β the same "runtime restore, not baked" pattern this image | |
| # already uses for the OpenSearch index and Neo4j graph, just for a | |
| # corpus-independent static artifact instead of per-run data. Publish | |
| # weights to that S3 path with scripts/publish_siglip2_model_to_s3.sh | |
| # whenever scripts/extract_siglip2_model.sh refreshes the vendored copy. | |
| COPY docker/hf-space/siglip2-model/model_repo/ensemble_image_model /models/ensemble_image_model | |
| COPY docker/hf-space/siglip2-model/model_repo/ensemble_text_model /models/ensemble_text_model | |
| COPY docker/hf-space/siglip2-model/model_repo/image_preprocessing /models/image_preprocessing | |
| COPY docker/hf-space/siglip2-model/model_repo/siglip2_vision_encoder_onnx/config.pbtxt /models/siglip2_vision_encoder_onnx/config.pbtxt | |
| COPY docker/hf-space/siglip2-model/model_repo/siglip2_text_encoder_onnx/config.pbtxt /models/siglip2_text_encoder_onnx/config.pbtxt | |
| RUN mkdir -p /models/siglip2_vision_encoder_onnx/1 /models/siglip2_text_encoder_onnx/1 | |
| COPY docker/hf-space/siglip2-model/model_repo/tokenizer /models/tokenizer | |
| # Owned by uid 1000: [program:siglip2-triton] restores the encoder weights into /models as that user. Some Space | |
| # hardware (rtx-pro-6000, 2026-10-21) runs the container as uid 1000 whatever USER says, so nothing may need root. | |
| RUN chown -R 1000:1000 /models | |
| # Python deps for the tokenizer + image_preprocessing Python-backend models β | |
| # resolved from pyproject.toml + uv.lock (the source of truth) at build time, | |
| # same as ../usdsearch/docker/Dockerfile.siglip2-triton itself does, so this | |
| # doesn't need a separately-maintained requirements.txt that can drift. | |
| # uv and virtualenv (below) are pinned so the third-party notice is | |
| # reproducible: scripts/generate_third_party_notice.sh reads both pins from | |
| # this file β re-run it after bumping either. | |
| COPY docker/hf-space/siglip2-model/pyproject.toml docker/hf-space/siglip2-model/uv.lock /workspace/ | |
| RUN pip install --no-cache-dir uv==0.12.22 \ | |
| && uv export --frozen --no-hashes --directory /workspace -o /workspace/requirements.txt \ | |
| && pip install --no-cache-dir -r /workspace/requirements.txt \ | |
| && rm /workspace/requirements.txt | |
| COPY docker/hf-space/siglip2-model/PACKAGE-LICENSES /PACKAGE-LICENSES | |
| # Attribution for anyone who pulls the image: this project's LICENSE plus the | |
| # third-party notices (scripts/generate_third_party_notice.sh). Root-level in | |
| # both build contexts (this repo for bake, the staged Space tree for HF); | |
| # licenses/ stays next to the notice so its relative links resolve. | |
| COPY LICENSE THIRD_PARTY_NOTICE.md /licenses/ | |
| COPY licenses /licenses/licenses | |
| # Same two size/vulnerability trims ../usdsearch/docker/Dockerfile.siglip2-triton | |
| # itself applies to this exact base image β carried over verbatim rather than | |
| # dropped, since they're cheap and free up real space (~1 GB+ for Nsight | |
| # Systems alone) on top of the FP16 savings above. | |
| RUN rm -rf /usr/local/cuda-13.2/NsightSystems-cli-2026.2.1 | |
| USER root | |
| # Non-root runtime uid/gid 1000, same convention docker/Dockerfile.hf-space | |
| # uses for every data-writing process in that image (matches | |
| # opensearchproject/opensearch's own "opensearch" user, 1000:1000). This | |
| # base image is Ubuntu 24.04 ("noble") β not verified live whether uid 1000 | |
| # is already taken by a user the NGC tritonserver image itself creates, so | |
| # this reuses it (rather than erroring) if it is: --chown=1000:1000 below | |
| # only cares that the numeric id resolves consistently, not which username | |
| # owns it. | |
| RUN if id -u 1000 >/dev/null 2>&1; then \ | |
| echo "uid 1000 already exists as $(getent passwd 1000 | cut -d: -f1) β reusing it"; \ | |
| else \ | |
| groupadd -g 1000 nvs && useradd -u 1000 -g 1000 -m -d /home/nvs -s /usr/sbin/nologin nvs; \ | |
| fi | |
| # python3.12-venv is requested | |
| # explicitly (Ubuntu splits the venv module out of the base python3.12 | |
| # package on some images) since this base is noble rather than bookworm and | |
| # hasn't been checked for what's preinstalled. | |
| # libssl3t64 and the virtualenv upgrade mirror usdsearch 1.5.0-rc.7's | |
| # docker/Dockerfile.siglip2-triton vulnerability fixes for this same base. | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| redis-server supervisor nginx curl python3.12-venv openssl libssl3t64 \ | |
| && rm -rf /var/lib/apt/lists/* \ | |
| && pip install --no-cache-dir --upgrade virtualenv==21.14.5 \ | |
| && rm -f /etc/nginx/sites-enabled/default \ | |
| && sed -i 's|^pid .*|pid /tmp/nginx.pid;|' /etc/nginx/nginx.conf \ | |
| && chown -R 1000:1000 /etc/nginx/conf.d /var/lib/nginx /var/log/nginx | |
| # nginx runs as uid 1000 (supervisord-gpu.conf): the pid file moves to /tmp, and the rendered config, temp and log | |
| # dirs belong to that user. Some Space hardware (rtx-pro-6000, 2026-10-21) runs the container as uid 1000 whatever | |
| # USER says, and nginx with user=root never started there (supervisord: "Can't drop privilege as nonroot user"). | |
| # The app venv: same /app/.venv path docker/Dockerfile.hf-space and | |
| # docker/hf-space/supervisord*.conf both hardcode. Installed from the same | |
| # repacked usdsearch wheels + constraints.txt as the NVCF variant β see that | |
| # Dockerfile's header comment for how wheels/ is produced and refreshed. | |
| # Upstream's own docker/Dockerfile.usdsearch compiles these wheels in a | |
| # python:3.12-bookworm builder stage but runs them in a | |
| # nvcr.io/nvidia/base/ubuntu:noble-20260217 *runtime* stage β the same OS | |
| # family as this Triton image's own base β so installing them here follows | |
| # upstream's own production direction (older-glibc build -> newer-glibc | |
| # run), not a new cross-distro risk. Not yet verified live in this repo, | |
| # though (see header comment). | |
| COPY docker/hf-space/wheels/ /tmp/usdsearch-wheels/ | |
| # env -u PYTHONPATH: with the Triton base image's PYTHONPATH (DALI's wheel dir) visible, pip treated | |
| # packages found there as installed and the venv came out without six (2026-09-29). | |
| # The venv APIs start without PYTHONPATH (supervisord-gpu.conf), so the venv must be complete. | |
| RUN python3.12 -m venv /app/.venv \ | |
| && env -u PYTHONPATH /app/.venv/bin/pip install --no-cache-dir \ | |
| --find-links /tmp/usdsearch-wheels \ | |
| --constraint /tmp/usdsearch-wheels/constraints.txt \ | |
| /tmp/usdsearch-wheels/*.whl \ | |
| && rm -rf /tmp/usdsearch-wheels \ | |
| && chown -R 1000:1000 /app/.venv | |
| # The vision checks' prepared asset views on disk (docker/hf-space/check_image_cache.py), on while the | |
| # CHECK_IMAGE_CACHE_DIR Space Variable is set (pipeline/config.py). The .pth loads it in every venv python. The | |
| # build fails unless it wraps the vendored llm_client and cached views come back byte-identical (--self-test), as PNG | |
| # (the default) and as JPEG (USDSEARCH_VISION_VALIDATION_IMAGE_FORMAT=jpeg, the Space Variable prod runs with). | |
| COPY docker/hf-space/check_image_cache.py docker/hf-space/check_image_cache.pth /tmp/check-image-hook/ | |
| RUN SP=$(env -u PYTHONPATH /app/.venv/bin/python -c 'import sysconfig; print(sysconfig.get_path("purelib"))') \ | |
| && install -m 644 /tmp/check-image-hook/check_image_cache.py /tmp/check-image-hook/check_image_cache.pth "$SP/" \ | |
| && rm -rf /tmp/check-image-hook \ | |
| && env -u PYTHONPATH CHECK_IMAGE_CACHE_DIR=/tmp/check-image-selftest /app/.venv/bin/python -m check_image_cache --self-test \ | |
| && env -u PYTHONPATH CHECK_IMAGE_CACHE_DIR=/tmp/check-image-selftest USDSEARCH_VISION_VALIDATION_IMAGE_FORMAT=jpeg \ | |
| /app/.venv/bin/python -m check_image_cache --self-test \ | |
| && rm -rf /tmp/check-image-selftest | |
| # hf-storage-api β see docker/Dockerfile.hf-space's own copy of this block | |
| # for the full explanation (identical here; this variant serves the same | |
| # corpus/storage backend, just with a different SigLIP2 backend). | |
| COPY docker/hf-space/hf-storage-api/hf_storage_api /app/hf-storage-api/src/hf_storage_api | |
| RUN GRPCIO_VERSION=$(env -u PYTHONPATH /app/.venv/bin/pip show grpcio | sed -n 's/^Version: //p') \ | |
| && env -u PYTHONPATH /app/.venv/bin/pip install --no-cache-dir "grpcio-health-checking==${GRPCIO_VERSION}" \ | |
| && env PYTHONPATH=/app/hf-storage-api/src /app/.venv/bin/python -c "import hf_storage_api.server" \ | |
| && chown -R 1000:1000 /app/hf-storage-api | |
| COPY --from=opensearch-src --chown=1000:1000 /usr/share/opensearch /usr/share/opensearch | |
| # Keep only opensearch-knn: deepsearch-api's hybrid search fuses results | |
| # client-side and the restored index uses only core analyzers + index.knn. | |
| # The other bundled plugins carry netty/httpcore5 jars flagged High by the | |
| # nSpect container scan (2026-10-02). Several passes because a plugin can't | |
| # be removed while another still extends it. With opensearch-security gone, | |
| # the entrypoint skips its DISABLE_SECURITY_PLUGIN handling. | |
| RUN cd /usr/share/opensearch \ | |
| && for pass in 1 2 3; do \ | |
| for p in $(ls plugins); do \ | |
| [ "$p" = opensearch-knn ] || bin/opensearch-plugin remove "$p" >/dev/null 2>&1 || true; \ | |
| done; \ | |
| done \ | |
| && [ "$(ls plugins)" = opensearch-knn ] || { echo "plugins left: $(ls plugins)" >&2; exit 1; } | |
| # Jackson jars no OpenSearch release fixes yet (nSpect, 2026-10-02): | |
| # - lib/jackson-core 3.2.2 -> 3.2.3 (GHSA-7hhh-6rmp-j9qf), a patch-level | |
| # drop-in from Maven Central, sha256-pinned. The old jar is removed by exact | |
| # name, so a base bump that already changed it fails here β re-check then. | |
| # - modules/ingest-geoip (jackson-databind/-core 2.22.2: GHSA-cxp5-3px4-pw24, | |
| # GHSA-wv8q-qhhj-9h54, ...) removed: no ingest pipeline uses GeoIP. | |
| RUN cd /usr/share/opensearch \ | |
| && rm -r modules/ingest-geoip lib/jackson-core-3.2.2.jar \ | |
| && curl -fsSL -o lib/jackson-core-3.2.3.jar \ | |
| https://repo1.maven.org/maven2/tools/jackson/core/jackson-core/3.2.3/jackson-core-3.2.3.jar \ | |
| && echo "a0c17e7e665a5e95c82f5fb45c0fec2ae3dc556c80f0016452c9c84cd23f3817 lib/jackson-core-3.2.3.jar" | sha256sum -c - \ | |
| && chown 1000:1000 lib/jackson-core-3.2.3.jar | |
| # See docker/Dockerfile.hf-space's own (much longer) comment on this same | |
| # block for the full k-NN/faiss library-path story β copied verbatim here | |
| # since it's the identical opensearchproject/opensearch source image and the | |
| # identical cross-image-copy cause. | |
| ENV OPENSEARCH_HOME=/usr/share/opensearch \ | |
| OPENSEARCH_PATH_CONF=/usr/share/opensearch/config \ | |
| PATH="/usr/share/opensearch/bin:/app/.venv/bin:${PATH}" \ | |
| LD_LIBRARY_PATH=/usr/share/opensearch/plugins/opensearch-knn/lib \ | |
| discovery.type=single-node \ | |
| DISABLE_SECURITY_PLUGIN=true \ | |
| DISABLE_INSTALL_DEMO_CONFIG=true \ | |
| bootstrap.memory_lock=false \ | |
| OPENSEARCH_JAVA_OPTS="-Xms1g -Xmx1g -Djava.library.path=/usr/share/opensearch/plugins/opensearch-knn/lib" | |
| # A Category pick sends one filter value per leaf, two Lucene clauses each, so | |
| # the default cap (1,024) refused 513+ values with HTTP 400 (2026-10-19: | |
| # Industrial + Residential + OEM = 519). 8192 takes ~4,000 values. | |
| ENV indices.query.bool.max_clause_count=8192 | |
| COPY --from=neo4j-src /opt/java/openjdk /opt/java/openjdk | |
| COPY --from=neo4j-src /var/lib/neo4j /var/lib/neo4j | |
| # Jackson jars no Neo4j release fixes yet (nSpect, 2026-10-02 β 2026.09.0 | |
| # ships the same ones): | |
| # - lib/jackson-core/-databind 2.22.2 -> 2.22.3 (GHSA-p6pp-m3f8-5c89, | |
| # GHSA-7hhh-6rmp-j9qf, GHSA-cxp5-3px4-pw24, GHSA-wv8q-qhhj-9h54), patch-level | |
| # drop-ins from Maven Central, sha256-pinned; old jars removed by exact name. | |
| # - lib/parquet-jackson removed: it shades jackson 2.22.1 (same advisories) | |
| # and has no fixed release. Only neo4j-admin's Parquet *import* uses it; | |
| # this image only runs `neo4j-admin database load` and the server. | |
| RUN cd /var/lib/neo4j/lib \ | |
| && rm jackson-core-2.22.2.jar jackson-databind-2.22.2.jar parquet-jackson-1.18.0.jar \ | |
| && curl -fsSL -o jackson-core-2.22.3.jar \ | |
| https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.22.3/jackson-core-2.22.3.jar \ | |
| && curl -fsSL -o jackson-databind-2.22.3.jar \ | |
| https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.22.3/jackson-databind-2.22.3.jar \ | |
| && printf '%s %s\n' \ | |
| 8a501126a385b25841915d839508f8a66e2a0dbc8a6709d055ef3b3e852b094c jackson-core-2.22.3.jar \ | |
| 556db5439e206114346043f68d200497dc96a0bca62a360a81784092ebd0e0a9 jackson-databind-2.22.3.jar \ | |
| | sha256sum -c - | |
| RUN mkdir -p /data /logs && chmod 777 /data /logs | |
| RUN cp /var/lib/neo4j/labs/apoc-*-core.jar /var/lib/neo4j/plugins/ | |
| RUN { \ | |
| echo "dbms.security.auth_enabled=false"; \ | |
| echo "server.memory.heap.initial_size=1G"; \ | |
| echo "server.memory.heap.max_size=1G"; \ | |
| echo "server.memory.pagecache.size=512M"; \ | |
| } >> /var/lib/neo4j/conf/neo4j.conf | |
| ENV NEO4J_HOME=/var/lib/neo4j \ | |
| PATH="/var/lib/neo4j/bin:/opt/java/openjdk/bin:${PATH}" | |
| COPY docker/hf-space/logging.yml /logging.yml | |
| COPY docker/hf-space/search_fields.yaml /app/search_fields.yaml | |
| # The query parser's system prompt β same as docker/Dockerfile.hf-space, see its comment. | |
| COPY docker/hf-space/llm_parse_prompt.txt /app/llm_parse_prompt.txt | |
| # The GPU-variant supervisord config β same six programs as | |
| # docker/hf-space/supervisord.conf plus [program:siglip2-triton], and | |
| # deepsearch-api's own command additionally waits on Triton's readiness | |
| # before execing uvicorn. See that file's header for the port-collision | |
| # reasoning (Triton's default HTTP port 8000 clashes with deepsearch-api's | |
| # own uvicorn; remapped to 8003 here). | |
| COPY docker/hf-space/supervisord-gpu.conf /etc/supervisor/conf.d/hf-space.conf | |
| # nginx's optional readiness gate (LIBRARY_MEDIA_GATE; see the script's header). | |
| COPY docker/hf-space/media-gate.sh /usr/local/bin/media-gate.sh | |
| COPY docker/hf-space/nginx.conf.template /etc/nginx/hf-space.conf.template | |
| COPY services/explorer/dist /usr/share/nginx/explorer | |
| COPY --chown=1000:1000 pipeline /app/hf-space-pipeline/pipeline | |
| # package-download (supervisord's program of that name) runs from this copy on the | |
| # venv deepsearch-api already brought (fastapi, uvicorn, grpcio, the storage_api | |
| # stubs, search_utils): fail the build, not the Space, if that ever stops importing. | |
| RUN cd /app/hf-space-pipeline && env -u PYTHONPATH /app/.venv/bin/python -c "import pipeline.package_download.app, pipeline.package_download.source, pipeline.package_download.sizes, search_utils.url_mapping" | |
| ARG ARTIFACT_S3_URI | |
| ARG ARTIFACT_S3_REGION=us-east-2 | |
| ARG CORPUS_NAME | |
| ENV ARTIFACT_S3_URI=${ARTIFACT_S3_URI} \ | |
| ARTIFACT_S3_REGION=${ARTIFACT_S3_REGION} \ | |
| CORPUS_NAME=${CORPUS_NAME} | |
| # βββ deepsearch-api config baked for this corpus/run ββββββββββββββββββββββββ | |
| # Same as docker/Dockerfile.hf-space's equivalent block, minus every | |
| # NVCF-specific ARG/env (SIGLIP2_NVCF_ENDPOINT/FUNCTION_ID and their | |
| # downstream SIGLIP2_TRITON_SERVER_* values) β this variant never talks to | |
| # NVCF at all. SIGLIP2_TRITON_SERVER_URL instead points at the local | |
| # siglip2-triton process's gRPC port (8001, loopback-only β nginx remains | |
| # the sole externally-proxied port, same as every other backend process in | |
| # this image), with no SSL and no auth headers, since nothing external ever | |
| # reaches it. | |
| ARG ES_NAME | |
| ARG S3_STORAGE_BUCKET_NAME | |
| ARG S3_STORAGE_REGION_NAME=us-west-2 | |
| ARG STORAGE_BACKEND_TYPE=s3 | |
| # DOWNLOAD_ENABLED / HF_STORAGE_API_TOKEN / SUBMIT_CONTENT_URL / STORAGE_API_* / DOWNLOAD_* / | |
| # PACKAGE_DOWNLOAD_* β see | |
| # docker/Dockerfile.hf-space's own copies of these comments for the full | |
| # explanation. | |
| # USDSEARCH_URL_MAPPING_MODE/_RULES β hf_space_build_args() derives them from | |
| # the repos (and pinned revisions) this run indexed; see url_mapping_rules(). | |
| ARG USDSEARCH_URL_MAPPING_MODE=off | |
| ARG USDSEARCH_URL_MAPPING_RULES=[] | |
| ARG DOWNLOAD_ENABLED=false | |
| ENV HF_STORAGE_API_TOKEN= \ | |
| DOWNLOAD_ENABLED=${DOWNLOAD_ENABLED} \ | |
| SUBMIT_CONTENT_URL=https://huggingface.co/datasets/nvidia/simready-central/discussions \ | |
| STORAGE_BACKEND_TYPE=${STORAGE_BACKEND_TYPE} \ | |
| S3_STORAGE_BUCKET_NAME=${S3_STORAGE_BUCKET_NAME} \ | |
| S3_STORAGE_REGION_NAME=${S3_STORAGE_REGION_NAME} \ | |
| opensearch_host=http://localhost:9200 \ | |
| opensearch_index_name=${ES_NAME}-ver5.0 \ | |
| opensearch_image_cache_index_name=${ES_NAME}-ver4.0-image-cache \ | |
| opensearch_use_ssl=false \ | |
| REDIS_URL=redis://localhost:6379 \ | |
| DEEPSEARCH_BACKEND_ASSET_GRAPH_SERVICE_URL=http://127.0.0.1:8010 \ | |
| ASSET_GRAPH_SERVICE_ENDPOINT=http://127.0.0.1:8010 \ | |
| ENABLE_ACCESS_VERIFICATION=False \ | |
| STORAGE_REQUIRE_AUTH=False \ | |
| VERIFY_ASSET_EXISTENCE=False \ | |
| verify_access=false \ | |
| ASSERT_ADMIN_USER=false \ | |
| USDSEARCH_VISION_VALIDATION_ENABLED=false \ | |
| USDSEARCH_LLM_PARSING_ENABLED=false \ | |
| # Validation limits are per deepsearch-api process: 32 checks in flight and a 31k-verdict cache in | |
| # each of the 16 processes (DEEPSEARCH_API_PROCESSES below), 512 and ~500k in all (Redis keeps every verdict | |
| # anyway). One search's page runs at most 16 at once (usdsearch's BATCH_CONCURRENCY). 2026-10-20 lab, l4x4 | |
| # shape with the check-image cache: 16 per process capped the engine side at ~155 checks/s (p95 of all badges | |
| # 14 s at 80 users); 32 held 3.2 s up to 240 users. | |
| USDSEARCH_VISION_VALIDATION_MAX_CONCURRENT=32 \ | |
| USDSEARCH_VISION_VALIDATION_CACHE_SIZE=31250 \ | |
| USDSEARCH_LLM_PARSING_FIELDS_FILEPATH=/app/search_fields.yaml \ | |
| USDSEARCH_LLM_PARSING_PROMPT_FILEPATH=/app/llm_parse_prompt.txt \ | |
| # Business telemetry β same as docker/Dockerfile.hf-space, see its comment. | |
| OTEL_SDK_DISABLED=false \ | |
| USE_SEARCH_TELEMETRY=true \ | |
| OTEL_TRACES_EXPORTER=false \ | |
| BACKEND_CONFIG_STR="backend_name: es-sample" \ | |
| DEFAULT_CUTOFF_THRESHOLD=0 \ | |
| HYBRID_SEARCH_SCORING_CONFIG_VECTOR_FIELDS="{\"siglip2-embedding.embedding\":{\"enabled\":true,\"weight\":1,\"field_name\":\"siglip2-embedding.embedding\",\"dimension\":1536}}" \ | |
| # Text-leg default β same as docker/Dockerfile.hf-space, see its comment. | |
| HYBRID_SEARCH_HYBRID_TEXT_CONFIG_WEIGHT=0.9 \ | |
| HYBRID_SEARCH_HYBRID_TEXT_CONFIG_CROSS_FIELD_OPERATOR=or \ | |
| HYBRID_SEARCH_HYBRID_TEXT_CONFIG_FIELDS="[{\"field\":\"name\",\"nested\":false,\"enabled\":true,\"weight\":2,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"name.simple\",\"nested\":false,\"enabled\":true,\"weight\":2,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"name.standard\",\"nested\":false,\"enabled\":true,\"weight\":2,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"usd_properties.value\",\"nested\":true,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"usd_properties.key\",\"nested\":true,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"tags.tag\",\"nested\":true,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"tags.value\",\"nested\":true,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"path\",\"nested\":false,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"path.tree\",\"nested\":false,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"path.tree_reversed\",\"nested\":false,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"__VISION_METADATA_FIELDS__\",\"nested\":false,\"enabled\":true,\"weight\":1,\"match_type\":\"fuzzy\",\"fuzzy_max_expansions\":1,\"wildcard\":true},{\"field\":\"name\",\"nested\":false,\"enabled\":true,\"weight\":5,\"match_type\":\"exact\",\"analyzer\":\"keyword\",\"wildcard\":false},{\"field\":\"name.standard\",\"nested\":false,\"enabled\":true,\"weight\":5,\"match_type\":\"exact\",\"analyzer\":\"keyword\",\"wildcard\":false}]" \ | |
| USDSEARCH_URL_MAPPING_MODE=${USDSEARCH_URL_MAPPING_MODE} \ | |
| USDSEARCH_URL_MAPPING_RULES=${USDSEARCH_URL_MAPPING_RULES} \ | |
| STORAGE_API_GRPC_ENDPOINT=127.0.0.1:50051 \ | |
| STORAGE_API_SSL=false \ | |
| STORAGE_API_IGNORE_FILEFOLDER_API=true \ | |
| DOWNLOAD_MAX_CONCURRENT=2 \ | |
| DOWNLOAD_QUEUE_TIMEOUT=120 \ | |
| DOWNLOAD_MAX_BUNDLE_BYTES=2000000000 \ | |
| PACKAGE_DOWNLOAD_PORT=8020 \ | |
| PACKAGE_DOWNLOAD_MAX_CONCURRENT=4 \ | |
| PACKAGE_DOWNLOAD_QUEUE_TIMEOUT=120 \ | |
| PACKAGE_DOWNLOAD_MAX_BUNDLE_BYTES=2000000000 \ | |
| STORAGE_API_THUMBNAIL_METADATA_FIELDS="[\"hf:thumbnail_url\"]" \ | |
| SIGLIP2_TRITON_SERVER_URL=localhost:8001 \ | |
| TRITON_SERVER_URL=localhost:8001 \ | |
| SIGLIP2_TRITON_SERVER_SSL=false \ | |
| # deepsearch-api processes, ONE uvicorn worker each, behind nginx's least_conn | |
| # upstream (supervisord-gpu.conf, nginx.conf.template). 16 for l4x4 (48 vCPU): | |
| # 2026-10-20 lab, l4x4 shape, 32 checks each: 16 processes held p95 of all badges at | |
| # 3.2 s up to 240 users (6.3 s at 300, CPU-bound); 6 processes reached ~100 users | |
| # with the CPU under 30 %. On a10g-large (12 vCPU) use 6: 8 cost ~20 % more CPU there. Must equal supervisord-gpu.conf's | |
| # numprocs: nginx renders its upstream from this, so never set it as a Space | |
| # Variable. DEEPSEARCH_API_WORKERS is no longer read (a leftover Space Variable | |
| # of that name does nothing). | |
| DEEPSEARCH_API_PROCESSES=16 \ | |
| PORT=7860 | |
| ARG RUN_ID | |
| ARG CORPUS_SHA256 | |
| ARG USDSEARCH_GIT_SHA | |
| LABEL org.opencontainers.image.title="usdsearch-hf-space-simready-central-gpu" \ | |
| org.opencontainers.image.description="Single-container MVP (OpenSearch+Neo4j+Redis+deepsearch-api, SigLIP2 via local Triton on GPU) for Hugging Face Spaces" \ | |
| com.nvidia.usdsearch.run_id="${RUN_ID}" \ | |
| com.nvidia.usdsearch.corpus_sha256="${CORPUS_SHA256}" \ | |
| com.nvidia.usdsearch.usdsearch_git_sha="${USDSEARCH_GIT_SHA}" | |
| # Longer start-period than docker/Dockerfile.hf-space's 10m: this variant | |
| # additionally waits on Triton loading ~3.6 GB of ONNX weights onto the GPU | |
| # before deepsearch-api's own uvicorn execs (see supervisord-gpu.conf). | |
| # Verified live against a small (1488-asset) dev corpus: Triton model load | |
| # took ~10s and the whole stack was healthy within ~20s total β 15m is | |
| # deliberately still a generous upper bound, not a tight one, since a larger | |
| # production corpus's OpenSearch bulk load / Neo4j offline load (the same | |
| # restore path docker/Dockerfile.hf-space already budgets 10m for) can take | |
| # much longer than this dev corpus did. | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=15m --retries=3 \ | |
| CMD curl -sf "http://localhost:${PORT}/health" || exit 1 | |
| EXPOSE 7860 | |
| ENTRYPOINT | |