From 31ba51626f066a2eec884eb18e985dc74d3e7f52 Mon Sep 17 00:00:00 2001 From: mohiit1502 Date: Sat, 3 Jan 2026 14:37:34 +0530 Subject: [PATCH] feat: Base image strategy to avoid 489MB downloads on every build - Dockerfile.base: contains TensorFlow, FAISS (build once, ~7min) - Dockerfile: uses base from Harbor (build fast, ~30s) - Jenkinsfile: BUILD_BASE=true parameter to rebuild base when needed First run: trigger with BUILD_BASE=true to create base image Subsequent runs: automatic, only copies app code --- Dockerfile | 30 ++---------------------------- Dockerfile.base | 26 ++++++++++++++++++++++++++ Jenkinsfile | 17 +++++++++++++---- 3 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 Dockerfile.base 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 )