1+ # syntax=docker/dockerfile:1.7-labs
12# =======================
23# Stage 1 - Builder
34# =======================
45FROM python:3.12-slim AS builder
56
67ARG ENABLE_CUDA=false
7-
8- WORKDIR /app
9-
108ENV PYTHONDONTWRITEBYTECODE=1 \
119 PYTHONUNBUFFERED=1 \
1210 PIP_NO_CACHE_DIR=1
1311
14- # System dependencies for building wheels
12+ WORKDIR /app
13+
14+ # Install system dependencies required for building wheels
1515RUN apt-get update && apt-get install -y --no-install-recommends \
1616 build-essential \
1717 curl \
@@ -21,79 +21,69 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2121# Install Poetry
2222RUN pip install --no-cache-dir poetry==2.2.1
2323
24- # Copy dependency files
24+ # Copy only the dependency descriptors first (cache friendly)
2525COPY pyproject.toml poetry.lock* /app/
2626
2727# Configure Poetry
2828RUN poetry config virtualenvs.create false
2929
30- # Install dependencies based on CUDA flag
31- RUN --mount=type=cache,id=poetry-cache,target=/root/.cache/pypoetry \
32- --mount=type=cache,id=pip-cache,target=/root/.cache/pip \
30+ # Install packages (use BuildKit cache mounts so subsequent builds are fast)
31+ # This layer will be reused as long as pyproject/poetry.lock don't change.
32+ RUN --mount=type=cache,target=/root/.cache/pypoetry \
33+ --mount=type=cache,target=/root/.cache/pip \
3334 if [ "$ENABLE_CUDA" = "true" ]; then \
3435 echo "Installing with CUDA support..." ; \
3536 poetry install --without dev --no-interaction --no-ansi --no-root; \
3637 else \
3738 echo "Installing CPU-only packages..." ; \
38- poetry install --without dev --no-interaction --no-ansi --no-root && \
39- pip uninstall -y torch torchvision && \
39+ # install declared dependencies
40+ poetry install --without dev --no-interaction --no-ansi --no-root; \
41+ # replace torch with CPU wheel (if on amd64), keep torch separate to avoid invalidation
42+ pip uninstall -y torch torchvision || true; \
4043 if [ "$TARGETARCH" = "amd64" ]; then \
4144 pip install --no-cache-dir \
42- torch==2.7.1+cpu \
43- torchvision==0.22.1+cpu \
44- --index-url https://download.pytorch.org/whl/cpu; \
45+ torch==2.7.1+cpu \
46+ torchvision==0.22.1+cpu \
47+ --index-url https://download.pytorch.org/whl/cpu; \
4548 else \
4649 pip install --no-cache-dir torch torchvision; \
4750 fi \
4851 fi
4952
50- # Clean up unnecessary files
51- RUN find /usr/local/lib/python3.12 -type d -name "tests" -exec rm -rf {} + 2>/dev/null || true && \
52- find /usr/local/lib/python3.12 -type d -name "test" -exec rm -rf {} + 2>/dev/null || true && \
53- find /usr/local/lib/python3.12 -type f -name "*.pyc" -delete && \
54- find /usr/local/lib/python3.12 -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
53+ # Remove tests/caches from site-packages to reduce image size
54+ RUN find /usr/local/lib/python3.12 -type d \( -name "tests" -o -name "test" -o -name "__pycache__" \) -exec rm -rf {} + 2>/dev/null || true \
55+ && find /usr/local/lib/python3.12 -type f -name "*.pyc" -delete
5556
5657# =======================
5758# Stage 2 - Runtime
5859# =======================
5960FROM python:3.12-slim AS runtime
6061
6162ARG ENABLE_CUDA=false
62-
63- WORKDIR /app
64-
6563ENV PYTHONDONTWRITEBYTECODE=1 \
6664 PYTHONUNBUFFERED=1 \
6765 PYTHONPATH=/app \
6866 PORT=8080 \
6967 ENABLE_CUDA=${ENABLE_CUDA}
7068
71- # Install only runtime dependencies
69+ WORKDIR /app
70+
71+ # Install small runtime system libs
7272RUN apt-get update && apt-get install -y --no-install-recommends \
7373 curl \
7474 libgomp1 \
7575 && rm -rf /var/lib/apt/lists/*
7676
77- # Copy only site-packages (not entire lib)
77+ # Copy installed site-packages and runtime binaries from builder
7878COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
7979COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
8080COPY --from=builder /usr/local/bin/gunicorn /usr/local/bin/gunicorn
8181
82- # Add non-root user
83- # RUN groupadd -r appuser && useradd -r -g appuser appuser
84-
85- # Copy local spaCy model
86- # COPY --chown=appuser:appuser spacy_models /app/spacy_models
87-
88- # Copy application code
89- # COPY --chown=appuser:appuser app /app/app
82+ # Copy application source last so code changes do not bust earlier caches
83+ COPY . /app
9084
9185# Create runtime directories
9286RUN mkdir -p /app/data/uploads /app/data/temp /app/logs
93- # RUN mkdir -p /app/data/uploads /app/data/temp /app/logs \
94- # && chown -R appuser:appuser /app
95-
96- # USER appuser
9787
9888EXPOSE 8080
9989
0 commit comments