# ── Stage 1: Builder ───────────────────────────────────────────────────── FROM python:3.11-slim AS builder # Install uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ WORKDIR /app # Install dependencies (cached layer — only rebuilds when deps change) COPY pyproject.toml uv.lock ./ RUN uv sync --frozen --no-dev --no-install-project # Copy source code COPY . . # ── Stage 2: Runtime ───────────────────────────────────────────────────── FROM python:3.11-slim # Install runtime system dependencies required by OpenCascade (CadQuery) RUN --mount=type=cache,target=/var/cache/apt \ --mount=type=cache,target=/var/lib/apt/lists \ apt-get update && apt-get install -y --no-install-recommends \ libgl1 libglib2.0-0 libx11-6 libxrender1 WORKDIR /app # Copy virtual environment from builder COPY --from=builder /app/.venv /app/.venv # Copy application source COPY --from=builder /app/config.yaml /app/ COPY --from=builder /app/config /app/config/ COPY --from=builder /app/core /app/core/ COPY --from=builder /app/server /app/server/ COPY --from=builder /app/agents /app/agents/ COPY --from=builder /app/web /app/web/ # Put venv on PATH ENV PATH="/app/.venv/bin:$PATH" ENV PYTHONUNBUFFERED=1 # Create output directory RUN mkdir -p /app/output EXPOSE 7860 CMD ["bash", "-c", "\ echo '=== NeuralCAD Container Starting ===' && \ echo 'Starting MCP CAD server on port 8000...' && \ python -m server.mcp --transport sse --port 8000 & \ MCP_PID=$! && \ sleep 3 && \ if ! kill -0 $MCP_PID 2>/dev/null; then echo 'ERROR: MCP server failed to start'; exit 1; fi && \ echo \"MCP server running (PID $MCP_PID)\" && \ export MCP_SERVER_URL=http://localhost:8000/sse && \ echo \"Starting web server on port ${PORT:-7860}...\" && \ exec python -m server.web --host 0.0.0.0 --port ${PORT:-7860} \ "]