From c3c014953208a6533137cd5b37066f1d95c7ce4c Mon Sep 17 00:00:00 2001 From: pjmalandrino Date: Fri, 20 Mar 2026 18:26:20 +0100 Subject: [PATCH] Add docker push --- .dockerignore | 20 ++++++++++ .github/workflows/release.yml | 49 +++++++++++++++++++++++ Dockerfile | 53 +++++++++++++++++++++++++ README.md | 32 ++++++++++----- document-parser/data/docling_studio.db | Bin 622592 -> 622592 bytes nginx.conf | 19 +++++++++ 6 files changed, 163 insertions(+), 10 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/release.yml create mode 100644 Dockerfile create mode 100644 nginx.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8837ce6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,20 @@ +.git/ +.github/ +*.md +LICENSE +.env +.env.* + +# Frontend build artifacts +frontend/node_modules/ +frontend/dist/ + +# Backend dev artifacts +document-parser/.venv/ +document-parser/__pycache__/ +document-parser/*.pyc +document-parser/.pytest_cache/ +document-parser/.mypy_cache/ +document-parser/.ruff_cache/ +document-parser/data/ +document-parser/uploads/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..cde2426 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Release Docker Image + +on: + push: + tags: + - "v*" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + release: + name: Build & push Docker image + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + + - uses: docker/setup-buildx-action@v3 + + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract version from tag + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest + + - uses: docker/build-push-action@v6 + with: + context: . + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4562860 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,53 @@ +# syntax=docker/dockerfile:1 +# ============================================================================= +# Docling Studio — single-image build (frontend + backend) +# +# Usage: +# docker build -t docling-studio . +# docker run -p 3000:3000 docling-studio +# ============================================================================= + +# --- Stage 1: Build frontend assets --- +FROM node:20-alpine AS frontend-build + +WORKDIR /build +COPY frontend/package*.json ./ +RUN npm ci +COPY frontend/ . +RUN npm run build + +# --- Stage 2: Runtime (Python + Nginx) --- +FROM python:3.12-slim + +# System deps: poppler (pdf2image), nginx, and OpenCV runtime libs +RUN apt-get update && apt-get install -y --no-install-recommends \ + poppler-utils \ + libgl1 \ + libglib2.0-0 \ + nginx \ + && rm -rf /var/lib/apt/lists/* + +# Python deps +WORKDIR /app +COPY document-parser/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Backend code +COPY document-parser/ . + +# Frontend static files +COPY --from=frontend-build /build/dist /usr/share/nginx/html + +# Nginx config +COPY nginx.conf /etc/nginx/sites-enabled/default + +# Data directories +RUN mkdir -p /app/uploads /app/data + +ENV UPLOAD_DIR=/app/uploads +ENV DB_PATH=/app/data/docling_studio.db + +EXPOSE 3000 + +# Start both nginx and uvicorn +CMD ["sh", "-c", "nginx && exec uvicorn main:app --host 127.0.0.1 --port 8000"] diff --git a/README.md b/README.md index 39ea588..38ab107 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,17 @@ frontend/src/ ## Quick Start -### Docker Compose (recommended) +### Docker (fastest) + +```bash +docker run -p 3000:3000 ghcr.io/scub-france/docling-studio:latest +``` + +Open [http://localhost:3000](http://localhost:3000) + +> **Note:** The first analysis takes longer as Docling downloads its ML models (~400 MB). Subsequent runs are fast. + +### Docker Compose (for development) ```bash git clone https://github.com/scub-france/Docling-Studio.git @@ -100,10 +110,6 @@ cd Docling-Studio docker compose up --build ``` -Open [http://localhost:3000](http://localhost:3000) - -> **Note:** The first analysis takes longer as Docling downloads its ML models (~400 MB). Subsequent runs are fast. - ### Local Development **Backend** (Python 3.12+): @@ -162,14 +168,20 @@ All configuration is done via environment variables. See [`.env.example`](.env.e | `DB_PATH` | `./data/docling_studio.db` | SQLite database path | | `CONVERSION_TIMEOUT` | `600` | Max seconds for a single Docling conversion | -## CI +## CI / Release -GitHub Actions runs on every push to `main` and on pull requests: +GitHub Actions pipelines (see [`.github/workflows/`](.github/workflows/)): -- **Backend job** — Python 3.12, pytest (99 tests) -- **Frontend job** — Node 20, vitest (87 tests) + vite build +| Workflow | Trigger | What it does | +|----------|---------|--------------| +| **CI** | push to `main`, pull requests | Backend tests (99) + Frontend tests (87) + build | +| **Release** | push tag `v*` | Build & push multi-arch Docker image to `ghcr.io` | -Both jobs run in parallel. See [`.github/workflows/ci.yml`](.github/workflows/ci.yml). +To publish a new version: +```bash +git tag v0.2.0 +git push origin v0.2.0 +``` ## Performance & System Requirements diff --git a/document-parser/data/docling_studio.db b/document-parser/data/docling_studio.db index 205f2f6fc35bb4ae5ed681408a9dc8d0f5509d70..84ff90ad7ef35cf637d73842b763b440a2e78e5f 100644 GIT binary patch delta 628 zcmb7>!Al!K7{#+$wJIsA=L!))5oEI8d^4Gu%|R#@p|sMX4Ia0%GqajvvWuzU%@9Ga z75@bfy-6Fe|4P8W!@E-or3Z!d@H;&C;C=7C!C-ALSo`)WSiM@>3RZu7zKQ0;+Fd28 zyu7d7jTRTa*UpA3;aq!fBMgS`c0^7AkxSx)bA)F?5v^@bY@X;Q00^!0`~AIit2pRs zlkPgB%XGVA4qZQe`?_HZbJ{3vuFLYMWAxWf(TlyTK8&X0cHbTMNw{7>lw#t0|~FoLj5Wec&zSfi;ZL%IRb z0vN7T|7JB@2wHp#Ov0!3~x@ZaEHznL-M l41erF9%m&2lK+LiIhCZi8008E{9lihn diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..e8c5b55 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,19 @@ +server { + listen 3000; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api/ { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_read_timeout 600s; + proxy_send_timeout 600s; + client_max_body_size 50M; + } +}