mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-24 05:35:31 -04:00
d47715036a
* fix(docker): make Real-ESRGAN installable on the Python 3.14 image realesrgan's deps basicsr/gfpgan/facexlib (unmaintained since 2022) read their version in setup.py via `exec(...); locals()['__version__']`, which raises KeyError on Python 3.13+ — PEP 667 made locals() in a function an independent snapshot that exec() can no longer mutate. That fails the Cookbook "install realesrgan" sdist build on the python:3.14 base. Add a `realesrgan-wheels` builder stage that fetches the pinned sdists, patches get_version() to exec into an explicit namespace dict, and builds wheels; the final stage installs them --no-deps so a later `pip install realesrgan` resolves from wheels instead of rebuilding the broken sdists. torch stays a runtime pull to keep the base image lean. Also add the runtime libs opencv-python (cv2) needs — libgl1, libglib2.0-0t64, libxcb1 — which the slim base omits; without them the install succeeds but `import cv2` dies with `libxcb.so.1: cannot open shared object file`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(cookbook): don't let a package's sys.exit() on import hang the deps panel The local optional-dependency probe imports each package in-process and catches ImportError / Exception. But a package can call sys.exit() at import time — e.g. rembg does `sys.exit(1)` when no onnxruntime backend loads. SystemExit is a BaseException, not Exception, so it escaped the probe, propagated out of the list_packages endpoint, and hung the whole Dependencies panel / worker (the UI loads forever). Catch (Exception, SystemExit) so one broken optional package is reported as not-usable instead of taking down the panel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
98 lines
4.3 KiB
Docker
98 lines
4.3 KiB
Docker
# ---- builder: patch + build wheels for Real-ESRGAN's broken-on-3.14 deps ----
|
|
# basicsr/gfpgan/facexlib read their version via exec()+locals()['__version__'],
|
|
# which raises KeyError on Python 3.13+ (PEP 667). Build patched wheels here so
|
|
# the final image / Cookbook never has to compile the broken sdists. See
|
|
# docker/build-realesrgan-wheels.sh for the full rationale.
|
|
FROM python:3.14-slim AS realesrgan-wheels
|
|
RUN apt-get update && apt-get install -y --no-install-recommends curl \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
COPY docker/build-realesrgan-wheels.sh /usr/local/bin/build-realesrgan-wheels.sh
|
|
RUN bash /usr/local/bin/build-realesrgan-wheels.sh /wheels
|
|
|
|
FROM python:3.14-slim
|
|
|
|
# System deps. tmux is required by Cookbook for background downloads/serves.
|
|
# openssh-client is required for Cookbook remote server tests, setup, probes,
|
|
# downloads, and serves from Docker installs.
|
|
# git/cmake are required when Cookbook builds llama.cpp on first llama.cpp
|
|
# launch inside Docker.
|
|
# nodejs/npm provide npx for the optional built-in Browser MCP server.
|
|
# gosu lets the entrypoint drop privileges cleanly so signals still reach
|
|
# uvicorn directly (no extra shell layer like `su`/`sudo` would add).
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
build-essential \
|
|
cmake \
|
|
curl \
|
|
git \
|
|
nodejs \
|
|
npm \
|
|
tmux \
|
|
openssh-client \
|
|
gosu \
|
|
libgl1 \
|
|
libglib2.0-0t64 \
|
|
libxcb1 \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# libgl1/libglib2.0-0t64/libxcb1 are runtime shared libs (libGL.so.1,
|
|
# libglib-2.0/libgthread, libxcb.so.1) that opencv-python (cv2) loads. The
|
|
# slim base omits them, so the Cookbook "install realesrgan" path imports cv2
|
|
# and dies with `libxcb.so.1: cannot open shared object file` despite a clean
|
|
# pip install. Using full opencv-python (not -headless) because basicsr/gfpgan/
|
|
# facexlib/realesrgan all depend on the `opencv-python` distribution by name.
|
|
|
|
# Docker CLI (client only — daemon stays on the host via the
|
|
# /var/run/docker.sock mount). The Debian `docker.io` package ships
|
|
# dockerd but not the client binary on slim, so grab the static client
|
|
# tarball from download.docker.com instead.
|
|
ARG DOCKER_CLI_VERSION=27.5.1
|
|
RUN ARCH="$(dpkg --print-architecture)" \
|
|
&& case "$ARCH" in \
|
|
amd64) DARCH=x86_64 ;; \
|
|
arm64) DARCH=aarch64 ;; \
|
|
*) echo "unsupported arch $ARCH"; exit 1 ;; \
|
|
esac \
|
|
&& curl -fsSL "https://download.docker.com/linux/static/stable/${DARCH}/docker-${DOCKER_CLI_VERSION}.tgz" \
|
|
-o /tmp/docker.tgz \
|
|
&& tar -xzf /tmp/docker.tgz -C /tmp \
|
|
&& install -m 0755 /tmp/docker/docker /usr/local/bin/docker \
|
|
&& rm -rf /tmp/docker /tmp/docker.tgz
|
|
|
|
WORKDIR /app
|
|
|
|
# Install Python deps first (layer cache). Optional extras (PyMuPDF AGPL, etc.)
|
|
# are opt-in so the default image stays MIT-core; see requirements-optional.txt.
|
|
ARG INSTALL_OPTIONAL=false
|
|
COPY requirements.txt requirements-optional.txt ./
|
|
RUN pip install --no-cache-dir -r requirements.txt \
|
|
&& if [ "$INSTALL_OPTIONAL" = "true" ]; then pip install --no-cache-dir -r requirements-optional.txt; fi
|
|
|
|
# Pre-install the patched basicsr/gfpgan/facexlib wheels built in the
|
|
# realesrgan-wheels stage (--no-deps keeps the image lean — torch & friends are
|
|
# pulled only when realesrgan is actually installed). With these dists already
|
|
# satisfied, the Cookbook's plain `pip install realesrgan` resolves them from
|
|
# wheels instead of rebuilding the sdists that fail on Python 3.14.
|
|
COPY --from=realesrgan-wheels /wheels/ /tmp/odysseus-wheels/
|
|
RUN pip install --no-cache-dir --no-deps /tmp/odysseus-wheels/*.whl \
|
|
&& rm -rf /tmp/odysseus-wheels
|
|
|
|
# Copy app code
|
|
COPY . .
|
|
|
|
# Create data directory (mount a volume here for persistence)
|
|
RUN mkdir -p data logs services/cache/search
|
|
|
|
# Entrypoint that drops to PUID/PGID (default 1000:1000) and repairs
|
|
# ownership on the bind-mounted /app/data and /app/logs. Without this,
|
|
# the container runs as root and writes root-owned files into host
|
|
# bind mounts — any later non-root run (or a host user trying to
|
|
# update them) silently fails on EPERM, breaking skill extraction,
|
|
# prefs persistence, mail attachments, etc.
|
|
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
RUN chmod +x /usr/local/bin/entrypoint.sh
|
|
|
|
EXPOSE 7000
|
|
|
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
|
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7000"]
|