diff --git a/Dockerfile b/Dockerfile index 1f2edb1..6ed53fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,36 +1,10 @@ # Visual Search Engine - API (8081) + Streamlit UI (3000) -# Single image serving both endpoints +# Uses pre-built base image from Harbor (has TensorFlow, FAISS, etc.) -FROM python:3.11-slim as builder +FROM harbor.armco.dev/library/visualsearch-base:latest WORKDIR /app -# Install build dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - && rm -rf /var/lib/apt/lists/* - -# Copy requirements and install dependencies -COPY requirements.txt . -RUN pip install --no-cache-dir --user -r requirements.txt - -# Production stage -FROM python:3.11-slim - -WORKDIR /app - -# Install runtime dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - libgomp1 \ - && rm -rf /var/lib/apt/lists/* - -# FAISS OpenMP threads -ENV OMP_NUM_THREADS=8 - -# Copy installed packages from builder -COPY --from=builder /root/.local /root/.local -ENV PATH=/root/.local/bin:$PATH - # Copy application code COPY api/ ./api/ COPY config.py . diff --git a/Dockerfile.base b/Dockerfile.base new file mode 100644 index 0000000..62a09a6 --- /dev/null +++ b/Dockerfile.base @@ -0,0 +1,26 @@ +# Base image with TensorFlow and heavy dependencies +# Build this ONCE and push to Harbor, then app builds use it +# Trigger rebuild only when requirements.txt changes + +FROM python:3.11-slim + +WORKDIR /app + +# Install build + runtime dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + libgomp1 \ + && rm -rf /var/lib/apt/lists/* + +# Install Python dependencies (the heavy 489MB download) +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Clean up build dependencies +RUN apt-get purge -y build-essential && apt-get autoremove -y && apt-get clean + +# Environment +ENV OMP_NUM_THREADS=8 +ENV PATH=/root/.local/bin:$PATH +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/Jenkinsfile b/Jenkinsfile index 3ef1410..6fea360 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,11 +1,20 @@ @Library('jenkins-shared@main') _ -// Single image serves both API (8081) and Streamlit UI (3000) +// Build base image (with TensorFlow) only when requirements.txt changes +// Then app builds are fast (~30s) using the cached base image + +def buildBase = params.BUILD_BASE ?: false + +def builds = [] +if (buildBase) { + // Build base image first - contains all heavy dependencies + builds.add([imageName: 'visualsearch-base', dockerfile: 'Dockerfile.base']) +} +// Always build app image - uses base from Harbor +builds.add([imageName: 'visualsearch', dockerfile: 'Dockerfile']) kanikoPipeline( repoName: 'visual-search-engine', branch: env.BRANCH_NAME ?: 'main', - builds: [ - [imageName: 'visualsearch', dockerfile: 'Dockerfile'] - ] + builds: builds )