diff --git a/engine/Dockerfile.cpu b/engine/Dockerfile.cpu index cb79b59..be9aa27 100644 --- a/engine/Dockerfile.cpu +++ b/engine/Dockerfile.cpu @@ -13,16 +13,32 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv WORKDIR /app +# Install CPU torch first, on its own, from the CPU index. +# +# Order matters: anything that depends on torch (sentence-transformers) will +# otherwise resolve the default CUDA build and pull ~2.7GB of nvidia-* wheels. +# Reinstalling torch afterwards replaces torch but leaves those wheels behind, +# orphaned and unused — which is how the CPU image ended up larger than the +# CUDA one. Installing CPU torch up front means nothing ever requests CUDA. +# +# Keeping it in its own layer also bounds the blob size: the registry drops +# uploads that take longer than 60s, so no single layer should approach ~3GB. +# Placing it before the source COPYs keeps this expensive layer cached when +# only application code changes. +RUN uv venv .venv && \ + . .venv/bin/activate && \ + UV_HTTP_TIMEOUT=600 uv pip install torch torchvision \ + --index-url https://download.pytorch.org/whl/cpu + COPY pyproject.toml ./ COPY kb/ kb/ COPY main.py ./ COPY VERSION ./ -RUN uv venv .venv && \ - . .venv/bin/activate && \ - uv pip install -e . && \ +# Remaining dependencies resolve against the CPU torch already present. +RUN . .venv/bin/activate && \ uv pip install "sentence-transformers[onnx]" && \ - uv pip install --reinstall torch torchvision --index-url https://download.pytorch.org/whl/cpu + uv pip install -e . ENV PATH="/app/.venv/bin:$PATH" ENV VIRTUAL_ENV="/app/.venv" diff --git a/engine/Dockerfile.nvidia b/engine/Dockerfile.nvidia index e9f602c..e1de270 100644 --- a/engine/Dockerfile.nvidia +++ b/engine/Dockerfile.nvidia @@ -13,14 +13,23 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv WORKDIR /app +# Install CUDA torch on its own, before the source COPYs. +# +# This is the bulk of the image (~2.8GiB compressed). Splitting it from the +# application install keeps it cached when only code changes, and keeps the +# app layer small. The registry drops any blob upload that takes longer than +# 60s, so this layer is deliberately the only large one. +RUN uv venv .venv && \ + . .venv/bin/activate && \ + UV_HTTP_TIMEOUT=600 uv pip install torch torchvision \ + --index-url https://download.pytorch.org/whl/cu130 + COPY pyproject.toml ./ COPY kb/ kb/ COPY main.py ./ COPY VERSION ./ -RUN uv venv .venv && \ - . .venv/bin/activate && \ - UV_HTTP_TIMEOUT=600 uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cu130 && \ +RUN . .venv/bin/activate && \ uv pip install -e . ENV PATH="/app/.venv/bin:$PATH"