mirror of
https://github.com/lfnovo/open-notebook.git
synced 2026-07-31 02:27:18 +00:00
Docling and local Crawl4AI are now opt-in, installed on first container startup via OPEN_NOTEBOOK_ENABLE_DOCLING / OPEN_NOTEBOOK_ENABLE_CRAWL4AI, keeping the default image lean (Crawl4AI un-bundled). Downloads cache on the /app/data volume; installs are blocking with loud logs and degrade-don't-die on failure. A GET /api/capabilities probe reports actual availability and the Settings UI gates the Docling/Crawl4AI engines and OCR toggle (with env-var hints) until the runtime is present. Docs folded from #1121 and rewritten to opt-in; ADR-007 added. Closes #1122. Closes #1105.
116 lines
5.4 KiB
Bash
Executable file
116 lines
5.4 KiB
Bash
Executable file
#!/bin/sh
|
|
# Open Notebook container entrypoint.
|
|
#
|
|
# Installs the OPT-IN heavy extraction runtimes (Docling, Crawl4AI local) when the
|
|
# operator enables them via env vars, then hands off to CMD (supervisord).
|
|
#
|
|
# OPEN_NOTEBOOK_ENABLE_DOCLING=true -> content-core[docling] (Docling engine, OCR, image sources)
|
|
# OPEN_NOTEBOOK_ENABLE_CRAWL4AI=true -> content-core[crawl4ai] + Chromium (local JS rendering)
|
|
#
|
|
# Design (see docs/7-DEVELOPMENT/decisions/ADR-007-optin-runtimes.md):
|
|
# - Blocking: installs finish before api/worker/frontend start.
|
|
# - Degrade, don't die: a failed install logs LOUDLY and boot continues; the
|
|
# runtime is simply reported unavailable by GET /api/capabilities.
|
|
# - Caches persist on the /app/data volume (UV_CACHE_DIR, PLAYWRIGHT_BROWSERS_PATH,
|
|
# HF_HOME), so a second boot reinstalls from cache instead of re-downloading.
|
|
# - The venv itself lives in the image layer (ephemeral per container), so we
|
|
# probe the actual venv each boot and reinstall when a fresh container lacks
|
|
# the extra. This is immune to Python-version bumps in the base image.
|
|
#
|
|
# POSIX /bin/sh (dash) compatible — no bashisms.
|
|
|
|
VENV_PY="/app/.venv/bin/python"
|
|
|
|
# Chromium's system libraries (installed via apt by `playwright install --with-deps`)
|
|
# live in the CONTAINER filesystem, which resets per container — so this marker
|
|
# lives there too (NOT on the volume), making --with-deps run once per container.
|
|
PLAYWRIGHT_DEPS_STAMP="/app/.playwright-system-deps.done"
|
|
|
|
log() { echo "[entrypoint] $*"; }
|
|
|
|
is_true() {
|
|
case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
|
|
1 | true | yes | on) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
has_module() {
|
|
"$VENV_PY" -c "import importlib.util, sys; sys.exit(0 if importlib.util.find_spec('$1') else 1)" 2>/dev/null
|
|
}
|
|
|
|
# Pin the extra to the base install's content-core version so its transitive deps
|
|
# stay compatible with what's already locked in the image.
|
|
ccore_version() {
|
|
"$VENV_PY" -c "import importlib.metadata as m; print(m.version('content-core'))" 2>/dev/null
|
|
}
|
|
|
|
# Ensure the cache directories exist on the (possibly freshly mounted) volume.
|
|
mkdir -p "${UV_CACHE_DIR:-/app/data/.cache/uv}" \
|
|
"${PLAYWRIGHT_BROWSERS_PATH:-/app/data/.cache/playwright}" \
|
|
"${HF_HOME:-/app/data/.cache/huggingface}" 2>/dev/null || true
|
|
|
|
CCORE_VERSION="$(ccore_version)"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Docling
|
|
# ---------------------------------------------------------------------------
|
|
if is_true "$OPEN_NOTEBOOK_ENABLE_DOCLING"; then
|
|
if has_module docling; then
|
|
log "Docling already installed; skipping."
|
|
elif [ -z "$CCORE_VERSION" ]; then
|
|
log "WARNING: could not determine content-core version; skipping Docling install."
|
|
else
|
|
log "Installing Docling (first start; this pulls a large ML stack — several hundred MB to a few GB — and can take several minutes)..."
|
|
if uv pip install --python "$VENV_PY" "content-core[docling]==${CCORE_VERSION}"; then
|
|
log "Docling installed. The Docling engine, OCR and image sources are now available."
|
|
else
|
|
log "WARNING: Docling install FAILED. Booting without it — the Docling engine, OCR and image sources will be unavailable. Fix connectivity and restart to retry."
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Crawl4AI (local). A remote server via CRAWL4AI_API_URL needs no local install.
|
|
# ---------------------------------------------------------------------------
|
|
if is_true "$OPEN_NOTEBOOK_ENABLE_CRAWL4AI"; then
|
|
if [ -n "$CRAWL4AI_API_URL" ]; then
|
|
log "CRAWL4AI_API_URL is set; using the remote Crawl4AI service (no local install)."
|
|
else
|
|
if has_module crawl4ai; then
|
|
log "Crawl4AI package already installed."
|
|
elif [ -z "$CCORE_VERSION" ]; then
|
|
log "WARNING: could not determine content-core version; skipping Crawl4AI install."
|
|
else
|
|
log "Installing Crawl4AI local runtime (first start; also downloads a Chromium browser ~150MB)..."
|
|
if uv pip install --python "$VENV_PY" "content-core[crawl4ai]==${CCORE_VERSION}"; then
|
|
log "Crawl4AI package installed."
|
|
else
|
|
log "WARNING: Crawl4AI install FAILED. Booting without local Crawl4AI — set CRAWL4AI_API_URL to use a remote server instead."
|
|
fi
|
|
fi
|
|
|
|
# Ensure the Chromium browser (persisted on the volume) and its system
|
|
# libraries (container FS, once per container) are present.
|
|
if has_module crawl4ai; then
|
|
if [ -f "$PLAYWRIGHT_DEPS_STAMP" ]; then
|
|
if "$VENV_PY" -m playwright install chromium >/dev/null 2>&1; then
|
|
log "Chromium browser ready."
|
|
else
|
|
log "WARNING: 'playwright install chromium' failed; local Crawl4AI may not render pages."
|
|
fi
|
|
else
|
|
log "Installing Chromium browser + system libraries (one-time for this container)..."
|
|
if "$VENV_PY" -m playwright install --with-deps chromium; then
|
|
touch "$PLAYWRIGHT_DEPS_STAMP"
|
|
log "Chromium browser + system libraries ready."
|
|
else
|
|
log "WARNING: 'playwright install --with-deps chromium' failed; local Crawl4AI may not render pages."
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
log "Starting Open Notebook."
|
|
exec "$@"
|