chore(docker): optimize image size with venv, slim builder, and dockerignore
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Docker build context exclusions
|
||||||
|
# Reducing the build context speeds up builds and prevents unnecessary cache
|
||||||
|
# invalidation when unrelated files change.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ── Version control ──────────────────────────────────────────────────────────
|
||||||
|
.git
|
||||||
|
|
||||||
|
# ── GitHub / CI tooling ──────────────────────────────────────────────────────
|
||||||
|
.github
|
||||||
|
|
||||||
|
# ── IDE / local dev ──────────────────────────────────────────────────────────
|
||||||
|
.vscode
|
||||||
|
.jules
|
||||||
|
|
||||||
|
# ── Pre-commit / linting config (not needed at runtime) ──────────────────────
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
pyproject.toml
|
||||||
|
codecov.yml
|
||||||
|
crowdin.yml
|
||||||
|
|
||||||
|
# ── Test suite ───────────────────────────────────────────────────────────────
|
||||||
|
tests/
|
||||||
|
requirements-dev.txt
|
||||||
|
coverage.json
|
||||||
|
COVERAGE_REPORT.md
|
||||||
|
.coverage
|
||||||
|
htmlcov/
|
||||||
|
.pytest_cache/
|
||||||
|
junit.xml
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
# ── Mobile app / browser extension / legacy placeholder ─────────────────────
|
||||||
|
# backend/ is an empty placeholder directory not part of the Python application
|
||||||
|
mobile/
|
||||||
|
browser-extension/
|
||||||
|
backend/
|
||||||
|
|
||||||
|
# ── Helm charts ──────────────────────────────────────────────────────────────
|
||||||
|
helm/
|
||||||
|
|
||||||
|
# ── Scripts (run before Docker build, output files are COPYd separately) ─────
|
||||||
|
scripts/
|
||||||
|
|
||||||
|
# ── Benchmark and one-off utility scripts ────────────────────────────────────
|
||||||
|
benchmark_*.py
|
||||||
|
fix_test*.py
|
||||||
|
run_fast_tests.sh
|
||||||
|
|
||||||
|
# ── Root-level Markdown files (docs/ is kept for docs-builder stage) ─────────
|
||||||
|
# Note: *.md only matches files at the root level, not inside subdirectories
|
||||||
|
*.md
|
||||||
|
|
||||||
|
# ── Python bytecode / compiled artifacts ─────────────────────────────────────
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
*.so
|
||||||
|
*.egg
|
||||||
|
*.egg-info/
|
||||||
|
|
||||||
|
# ── Virtual environments ──────────────────────────────────────────────────────
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
|
||||||
|
# ── Environment / secret files ───────────────────────────────────────────────
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# ── Runtime state files ───────────────────────────────────────────────────────
|
||||||
|
*.log
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# ── Build artifacts ───────────────────────────────────────────────────────────
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
.cache/
|
||||||
|
.mypy_cache/
|
||||||
|
.ruff_cache/
|
||||||
|
site/
|
||||||
|
docs_build/
|
||||||
|
|
||||||
|
# ── Editor temp files ─────────────────────────────────────────────────────────
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
+37
-19
@@ -1,14 +1,34 @@
|
|||||||
# Use multi-stage build for a smaller final image
|
# syntax=docker/dockerfile:1
|
||||||
FROM python:3.14.1 AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
# ── Stage 1: Python dependency builder ──────────────────────────────────────
|
||||||
|
# Use the same slim variant as the runtime to keep Python versions in sync.
|
||||||
|
# build-essential + libffi-dev cover the few packages (e.g. cryptography) that
|
||||||
|
# need a C compiler; they are discarded after this stage.
|
||||||
|
FROM python:3.14.3-slim AS builder
|
||||||
|
|
||||||
# Copy requirements first for better layer caching
|
WORKDIR /build
|
||||||
COPY requirements.txt /app/
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# ── Documentation build stage ───────────────────────────────────────────────
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
FROM python:3.14.1-slim AS docs-builder
|
build-essential \
|
||||||
|
libffi-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create an isolated virtual environment so only installed packages are copied
|
||||||
|
# to the runtime image (no pip, setuptools, or other builder artefacts).
|
||||||
|
RUN python -m venv /opt/venv
|
||||||
|
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH" \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PIP_NO_CACHE_DIR=1
|
||||||
|
|
||||||
|
COPY requirements.txt /build/
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt \
|
||||||
|
# Remove bytecode and cache to keep the venv lean
|
||||||
|
&& find /opt/venv -type f -name "*.pyc" -delete \
|
||||||
|
&& find /opt/venv -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
# ── Stage 2: Documentation builder ──────────────────────────────────────────
|
||||||
|
FROM python:3.14.3-slim AS docs-builder
|
||||||
|
|
||||||
WORKDIR /docs
|
WORKDIR /docs
|
||||||
|
|
||||||
@@ -23,14 +43,13 @@ COPY mkdocs.yml /docs/mkdocs.yml
|
|||||||
# Build the static documentation site
|
# Build the static documentation site
|
||||||
RUN mkdocs build --config-file /docs/mkdocs.yml --site-dir /docs/docs_build
|
RUN mkdocs build --config-file /docs/mkdocs.yml --site-dir /docs/docs_build
|
||||||
|
|
||||||
# Second stage for the actual runtime
|
# ── Stage 3: Runtime image ───────────────────────────────────────────────────
|
||||||
FROM python:3.14.3-slim
|
FROM python:3.14.3-slim
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy installed packages from builder stage
|
# Copy only the pre-built virtual environment from the builder
|
||||||
COPY --from=builder /usr/local/lib/python3.14/site-packages /usr/local/lib/python3.14/site-packages
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
|
||||||
|
|
||||||
# Install system-level OCR tools required for local OCR workflows:
|
# Install system-level OCR tools required for local OCR workflows:
|
||||||
# tesseract-ocr – OCR engine used by pytesseract and ocrmypdf
|
# tesseract-ocr – OCR engine used by pytesseract and ocrmypdf
|
||||||
@@ -62,15 +81,14 @@ COPY ./RUNTIME_INFO /app/RUNTIME_INFO
|
|||||||
# Copy the pre-built MkDocs documentation site (served at /help)
|
# Copy the pre-built MkDocs documentation site (served at /help)
|
||||||
COPY --from=docs-builder /docs/docs_build /app/docs_build
|
COPY --from=docs-builder /docs/docs_build /app/docs_build
|
||||||
|
|
||||||
# Create runtime_info directory
|
# Create necessary runtime directories in a single layer
|
||||||
RUN mkdir -p /app/runtime_info
|
RUN mkdir -p /app/runtime_info /workdir
|
||||||
|
|
||||||
# Create necessary directories
|
|
||||||
RUN mkdir -p /workdir
|
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV PYTHONPATH=/app
|
ENV PATH="/opt/venv/bin:$PATH" \
|
||||||
ENV PYTHONUNBUFFERED=1
|
PYTHONPATH=/app \
|
||||||
|
PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
|
|
||||||
# Expose the port the app runs on
|
# Expose the port the app runs on
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|||||||
+35
-13
@@ -1,13 +1,31 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
# Local development Dockerfile (avoids CI-only build metadata files)
|
# Local development Dockerfile (avoids CI-only build metadata files)
|
||||||
FROM python:3.14.1 AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
# ── Stage 1: Python dependency builder ──────────────────────────────────────
|
||||||
|
FROM python:3.14.3-slim AS builder
|
||||||
|
|
||||||
COPY requirements.txt /app/
|
WORKDIR /build
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
# ── Documentation build stage ───────────────────────────────────────────────
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
FROM python:3.14.1-slim AS docs-builder
|
build-essential \
|
||||||
|
libffi-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create an isolated virtual environment
|
||||||
|
RUN python -m venv /opt/venv
|
||||||
|
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH" \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PIP_NO_CACHE_DIR=1
|
||||||
|
|
||||||
|
COPY requirements.txt /build/
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt \
|
||||||
|
&& find /opt/venv -type f -name "*.pyc" -delete \
|
||||||
|
&& find /opt/venv -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
# ── Stage 2: Documentation builder ──────────────────────────────────────────
|
||||||
|
FROM python:3.14.3-slim AS docs-builder
|
||||||
|
|
||||||
WORKDIR /docs
|
WORKDIR /docs
|
||||||
|
|
||||||
@@ -19,23 +37,25 @@ COPY mkdocs.yml /docs/mkdocs.yml
|
|||||||
|
|
||||||
RUN mkdocs build --config-file /docs/mkdocs.yml --site-dir /docs/docs_build
|
RUN mkdocs build --config-file /docs/mkdocs.yml --site-dir /docs/docs_build
|
||||||
|
|
||||||
FROM python:3.14.1-slim
|
# ── Stage 3: Runtime image ───────────────────────────────────────────────────
|
||||||
|
FROM python:3.14.3-slim
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=builder /usr/local/lib/python3.14/site-packages /usr/local/lib/python3.14/site-packages
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
COPY --from=builder /usr/local/bin /usr/local/bin
|
|
||||||
|
|
||||||
# Install system-level OCR tools required for local OCR workflows:
|
# Install system-level OCR tools required for local OCR workflows:
|
||||||
# tesseract-ocr – OCR engine used by pytesseract and ocrmypdf
|
# tesseract-ocr – OCR engine used by pytesseract and ocrmypdf
|
||||||
# ghostscript – required by ocrmypdf for PDF/PS operations
|
# ghostscript – required by ocrmypdf for PDF/PS operations
|
||||||
# poppler-utils – provides pdfinfo/pdftoppm used by pdf2image
|
# poppler-utils – provides pdfinfo/pdftoppm used by pdf2image
|
||||||
# unpaper – optional deskewing pre-processor used by ocrmypdf
|
# unpaper – optional deskewing pre-processor used by ocrmypdf
|
||||||
|
# wget – used by ocr_language_manager to download tessdata files
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
tesseract-ocr \
|
tesseract-ocr \
|
||||||
ghostscript \
|
ghostscript \
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
unpaper \
|
unpaper \
|
||||||
|
wget \
|
||||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY ./app /app/app
|
COPY ./app /app/app
|
||||||
@@ -53,11 +73,13 @@ COPY --from=docs-builder /docs/docs_build /app/docs_build
|
|||||||
RUN echo "local" > /app/GIT_SHA \
|
RUN echo "local" > /app/GIT_SHA \
|
||||||
&& echo "local" > /app/RUNTIME_INFO
|
&& echo "local" > /app/RUNTIME_INFO
|
||||||
|
|
||||||
RUN mkdir -p /app/runtime_info
|
# Create necessary runtime directories in a single layer
|
||||||
RUN mkdir -p /workdir
|
RUN mkdir -p /app/runtime_info /workdir
|
||||||
|
|
||||||
ENV PYTHONPATH=/app
|
ENV PATH="/opt/venv/bin:$PATH" \
|
||||||
ENV PYTHONUNBUFFERED=1
|
PYTHONPATH=/app \
|
||||||
|
PYTHONUNBUFFERED=1 \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user