FROM python:3.13-slim # opencv-python (pulled in transitively by vs-core/vs-task/vs-measure/vs-pm2d) # needs libGL and glib at runtime even though it is never imported by name here. RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1 libglib2.0-0 \ && rm -rf /var/lib/apt/lists/* COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv WORKDIR /app COPY pyproject.toml uv.lock ./ COPY vendor/ ./vendor/ RUN uv sync --extra vision-worker --frozen --no-dev COPY src/vision/ ./src/vision/ COPY src/vision_worker/ ./src/vision_worker/ # Ruling R8: the version is stamped at build time, not discovered at runtime. # COPY vendor/ above does not bring vendor/visionsuite/.git along - it is a # gitlink file pointing at ../../.git/modules/vendor/visionsuite, which lives # outside the build context - so `git rev-parse HEAD` cannot work in here. # Pass the submodule's commit in from the host, which does have git: # VISION_ENGINE_VERSION=$(git -C vendor/visionsuite rev-parse HEAD) \ # docker compose build vision ARG VISION_ENGINE_VERSION # I4: a build without the commit must fail now, at build time - not later, at # every request including /health, with a container Docker still reports as # healthy because no healthcheck existed to say otherwise. RUN test -n "$VISION_ENGINE_VERSION" || { \ echo "VISION_ENGINE_VERSION is required. Build with:"; \ echo ' VISION_ENGINE_VERSION=$(git -C vendor/visionsuite rev-parse HEAD) docker compose build vision'; \ exit 1; \ } ENV VISION_ENGINE_VERSION=${VISION_ENGINE_VERSION} EXPOSE 8100 # Two workers, not four: each holds the vision stack in memory. CMD ["uv", "run", "uvicorn", "src.vision_worker.main:app", \ "--host", "0.0.0.0", "--port", "8100", "--workers", "2"]