Ctrl K
ComunidadGuías…

Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# ============================================================================
# Shrinkerr — portable, multi-arch, CPU-encoding image.
#
# Runs on:
#   - linux/amd64  (x86_64 servers, Docker Desktop on Intel/AMD, etc.)
#   - linux/arm64  (Apple Silicon, Raspberry Pi 5, Ampere cloud hosts, …)
#
# Encoding: libx265 on the CPU. This image contains NO CUDA runtime — it's
# deliberately small and portable. If your host has an NVIDIA GPU and you
# want NVENC (hardware) encoding, pull the companion image instead:
#   ghcr.io/<owner>/shrinkerr:nvenc     (built from Dockerfile.nvenc)
# Shrinkerr's runtime capability detection transparently falls back to
# libx265 in this image; the Monitor page shows "Using CPU encoding".
# ============================================================================

# Stage 1: build the frontend bundle.
# Pinning --platform=$BUILDPLATFORM makes sure buildx does the npm step on
# the native architecture of the builder host (the runner, not the target),
# so cross-compilation for arm64 doesn't re-run npm inside QEMU. The output
# is pure JS/CSS, so it's portable across target architectures.
FROM --platform=$BUILDPLATFORM mirror.gcr.io/library/node:20-slim AS frontend-build
WORKDIR /app/frontend
COPY frontend/package.json frontend/package-lock.json* ./
RUN npm ci
COPY frontend/ ./
RUN npm run build

# Stage 2: runtime image.
# python:3.11-slim-bookworm is multi-arch (amd64 + arm64) and much smaller
# than the ubuntu/CUDA image used by the :nvenc variant.
#
# v0.7.4: pulled from Google's mirror.gcr.io instead of docker.io to avoid
# Docker Hub anonymous + authenticated pull rate limits (200/6h on free)
# from cooking the CI matrix (4 variants × 2 archs × multi-stage). The
# mirror is a byte-for-byte proxy of Docker Hub's `library/*` namespace,
# requires no auth, and has no rate limit. Same applies to the node:20-slim
# pull in stage 1 above, and to Dockerfile.nvenc.
FROM mirror.gcr.io/library/python:3.11-slim-bookworm
ARG TARGETARCH

# curl + xz-utils only needed for the ffmpeg download step below; purged at
# the end of that step so they don't bloat the final image layer.
#
# VA-API runtime libraries (~30 MB total) let ffmpeg's hevc_qsv (Intel
# Quick Sync) and hevc_vaapi (Intel + AMD generic VA-API) actually run
# when the host passes /dev/dri through. Harmless on hosts without an
# Intel/AMD GPU — ffmpeg simply doesn't surface those encoders. v0.3.67+.
#
# Cross-arch note (v0.3.71): the Intel iHD + i965 drivers are AMD64-only
# in Debian (Intel iGPUs don't exist on ARM, and there's no upstream arm64
# build of `intel-media-va-driver-non-free`). Without this gate the v0.3.67
# build broke the multi-arch publish for several releases — the arm64 leg
# failed with `Unable to locate package intel-media-va-driver-non-free`.
# The arm64 leg keeps the arch-agnostic packages (libva, mesa-va-drivers,
# vainfo) which are still useful for AMD GPUs reachable on arm64 hosts
# (rare but not impossible — Ampere + Radeon, Pi + USB-C eGPU, etc.).
#
#   libva2 + libva-drm2            → core VA-API runtime (multi-arch)
#   mesa-va-drivers                → AMD radeonsi (multi-arch)
#   vainfo                         → diagnostic (multi-arch)
#   intel-media-va-driver-non-free → Intel iHD (Gen9+: Skylake / Arc) — AMD64 ONLY
#   i965-va-driver                 → Intel legacy (Gen8 and older) — AMD64 ONLY
#
# `intel-media-va-driver-non-free` lives in Debian's `non-free` component;
# enabled below before the conditional install. Source-open driver,
# "non-free" naming is historical from when it shipped as a binary blob.
RUN set -eux; \
    apt-get update; \
    # v0.5.13: pull latest security patches at build time. Halves the
    # High/Medium CVE count Docker Scout reports without changing the
    # base image. Cheap and low-risk — security updates are minor
    # bumps within the bookworm release line.
    apt-get upgrade -y --no-install-recommends; \
    apt-get install -y --no-install-recommends curl xz-utils libarchive-tools libbluray-bin mkvtoolnix \
        tesseract-ocr tesseract-ocr-eng tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-jpn tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ara \
        libgl1 libglib2.0-0; \
    if [ "${TARGETARCH}" = "amd64" ]; then \
        # All VA-API packages (runtime libs + Intel iHD + AMD radeonsi +
        # diagnostic) only on amd64. arm64 builds keep the minimal
        # pre-v0.3.67 install since Intel iGPUs are x86-only and AMD
        # GPUs on arm64 hosts are exceptionally rare.
        #
        # Enable non-free + non-free-firmware components by EDITING the
        # existing DEB822 sources file (python:3.11-slim-bookworm uses
        # `/etc/apt/sources.list.d/debian.sources`) rather than dropping
        # a second `.list`. Adding a parallel `bookworm` repo without a
        # `Signed-By:` directive makes apt fail with
        #   E: Conflicting values set for option Signed-By regarding
        #      source http://deb.debian.org/debian/ bookworm:
        #      /usr/share/keyrings/debian-archive-keyring.gpg !=
        # which is what bit v0.3.67 → v0.3.73. The sed targets both the
        # `bookworm` and `bookworm-security` stanzas in the same file
        # (one substitution per Components line). v0.3.74+.
        sed -i 's|^Components: main$|Components: main contrib non-free non-free-firmware|' \
            /etc/apt/sources.list.d/debian.sources; \
        apt-get update; \
        apt-get install -y --no-install-recommends \
            libva-drm2 \
            mesa-va-drivers \
            vainfo \
            intel-media-va-driver-non-free \
            i965-va-driver \
            libvpl2 libmfx1 \
            build-essential cmake meson ninja-build pkg-config \
            libdrm-dev libigdgmm-dev libpciaccess-dev bzip2; \
            # libvpl2: Intel oneVPL dispatcher. libmfx1: legacy MediaSDK
            # runtime — kept as a fallback for older HW; the modern
            # libmfx-gen runtime built below takes precedence on Gen9+.
            # build-essential + cmake + meson + ninja + dev headers:
            # temporarily installed for the libva and vpl-gpu-rt builds
            # below. Purged at the end of the layer.
        #
        # === libva 2.22 from source (v0.3.88+) ============================
        #
        # The BtbN n7.x ffmpeg static builds are compiled against
        # libva ≥ 2.20 (which introduced `vaMapBuffer2`). Debian
        # bookworm ships libva 2.17 even via backports — every apt-
        # installable libva on bookworm is too old, and the runtime
        # symbol lookup for `vaMapBuffer2` fails the first time
        # hevc_vaapi tries to encode. We replace the system libva with
        # an upstream 2.22.x build. libva 2.x is ABI-stable, so the
        # iHD / i965 / mesa drivers (compiled against 2.17) continue
        # to work against 2.22 without rebuilding. ~30s build.
        LIBVA_VER=2.22.0; \
        curl -fsSL "https://github.com/intel/libva/releases/download/${LIBVA_VER}/libva-${LIBVA_VER}.tar.bz2" -o /tmp/libva.tar.bz2; \
        mkdir -p /tmp/libva-src; \
        tar xjf /tmp/libva.tar.bz2 -C /tmp/libva-src --strip-components=1; \
        cd /tmp/libva-src; \
        meson setup build --prefix=/usr -Dlibdir=lib/x86_64-linux-gnu --buildtype=release; \
        ninja -C build install; \
        cd /; rm -rf /tmp/libva-src /tmp/libva.tar.bz2; \
        ldconfig; \
        #
        # === vpl-gpu-rt (libmfx-gen) from source (v0.3.89+) ===============
        #
        # Intel's modern oneVPL GPU runtime — what Sonarr/Radarr-tier
        # users on current Ubuntu/Arch get from `libmfx-gen1` package.
        # Not packaged for Debian 12 or Ubuntu 22.04. Without this,
        # libvpl2 (dispatcher) falls back to legacy libmfx1, which
        # rejects libva-2.22 VADisplays with `MFX_ERR_INCOMPATIBLE_-
        # VIDEO_PARAM (-17)` — that's what bit users testing v0.3.84
        # → v0.3.88. With libmfx-gen.so.1.2 installed, the dispatcher
        # finds the modern runtime first and QSV works against modern
        # libva + iHD drivers. ~3 min build on x86_64.
        VPL_VER=24.4.4; \
        curl -fsSL "https://github.com/intel/vpl-gpu-rt/archive/refs/tags/intel-onevpl-${VPL_VER}.tar.gz" -o /tmp/vpl.tar.gz; \
        mkdir -p /tmp/vpl-src; \
        tar xzf /tmp/vpl.tar.gz -C /tmp/vpl-src --strip-components=1; \
        cd /tmp/vpl-src; \
        # Memory-conservative configure (v0.3.92+). The default
        # `cmake --build --parallel` uses every core, and a
        # multi-arch buildx build runs both leg's compile/link
        # steps concurrently — easy way to exceed 7 GB on GHA
        # free runners and OOM-kill the runner mid-link
        # (lost-communication errors at the mfx_common_hw stage).
        # Mitigations:
        #   MinSizeRel + IPO=OFF  → smaller object files, less
        #                           template-instantiation RAM
        #   BUILD_TESTS=OFF       → skip test-suite compilation
        #   --parallel 1          → serialize compile + link;
        #                           slower (~10 min vs ~5 min)
        #                           but stays under the budget
        cmake -B build \
            -DCMAKE_BUILD_TYPE=MinSizeRel \
            -DCMAKE_INSTALL_PREFIX=/usr \
            -DCMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu \
            -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \
            -DBUILD_TESTS=OFF; \
        cmake --build build --parallel 1; \
        cmake --install build; \
        cd /; rm -rf /tmp/vpl-src /tmp/vpl.tar.gz; \
        ldconfig; \
        #
        # Purge build toolchain — keep the image lean. The runtime libs
        # (libva-drm2, mesa-va-drivers, libvpl2, libmfx1, …) stay
        # because they were explicitly installed above; apt sees them as
        # user-installed and won't auto-remove them.
        apt-get purge -y build-essential cmake meson ninja-build pkg-config libdrm-dev libigdgmm-dev libpciaccess-dev bzip2; \
        apt-get autoremove -y; \
        #
        # === Intel media driver 25.2.4 (v0.9.160) ==========================
        #
        # Bookworm's iHD driver (23.1) is too old for Arc / Flex cards (DG2,
        # ATS-M): vaInitialize fails with "iHD_drv_video.so init failed"
        # (GitHub issue, Flex 170). Intel's own build from its Ubuntu 22.04
        # repo needs only glibc 2.34, runs on bookworm, is built for libva
        # 2.22 (the one above) and supports Broadwell through Battlemage.
        # Pinned by version and hash; it replaces bookworm's driver + gmmlib.
        INTEL_POOL=https://repositories.intel.com/gpu/ubuntu/pool/unified/i; \
        curl -fsSL --retry 5 --retry-delay 3 -o /tmp/libigdgmm12.deb "${INTEL_POOL}/intel-gmmlib/libigdgmm12_22.7.2-1135~22.04_amd64.deb"; \
        curl -fsSL --retry 5 --retry-delay 3 -o /tmp/intel-media.deb "${INTEL_POOL}/intel-media-driver-non-free/intel-media-va-driver-non-free_25.2.4-1146~22.04_amd64.deb"; \
        printf '%s  %s\n' \
            c8b3dfbc044735e9502fd4b8e9560f9118afd49755f8caa4d173b0a84044638d /tmp/libigdgmm12.deb \
            fa22334f9431985f2b09748c365e61f54ff7b9b2a01a9c6d1cf24c1075a315fc /tmp/intel-media.deb \
            | sha256sum -c -; \
        apt-get install -y --no-install-recommends /tmp/libigdgmm12.deb /tmp/intel-media.deb; \
        rm -f /tmp/libigdgmm12.deb /tmp/intel-media.deb; \
    else \
        echo "Skipping VA-API runtime on ${TARGETARCH} (amd64-only in this image)"; \
    fi; \
    rm -rf /var/lib/apt/lists/*

# Install ffmpeg static build from BtbN (includes libx265, libvmaf, x264).
# BtbN publishes per-architecture assets under the rolling `latest` release;
# asset filenames differ between master and tagged (nX.Y) releases.
#   master: ffmpeg-master-latest-{linux64,linuxarm64}-gpl.tar.xz
#   nX.Y:   ffmpeg-nX.Y-latest-{linux64,linuxarm64}-gpl-X.Y.tar.xz
ARG FFMPEG_BUILD=n7.1
RUN set -e; \
    case "${TARGETARCH}" in \
        amd64) ARCH_TAG="linux64" ;; \
        arm64) ARCH_TAG="linuxarm64" ;; \
        *)     echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 2 ;; \
    esac; \
    case "${FFMPEG_BUILD}" in \
        master) FF_URL="https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-${ARCH_TAG}-gpl.tar.xz" ;; \
        n*)     FF_VER="${FFMPEG_BUILD#n}"; \
                FF_URL="https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-${FFMPEG_BUILD}-latest-${ARCH_TAG}-gpl-${FF_VER}.tar.xz" ;; \
        *)      echo "Unknown FFMPEG_BUILD: ${FFMPEG_BUILD} (expected 'master' or 'nX.Y')" >&2; exit 2 ;; \
    esac; \
    echo "Installing ffmpeg ${FFMPEG_BUILD} for ${TARGETARCH}: ${FF_URL}"; \
    # v0.9.105: download to a file with retries, THEN extract. Piping curl
    # straight into tar can't retry a mid-stream cut (tar has already consumed
    # a partial stream) — that flaked the arm64 leg under slow QEMU emulation.
    curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors "${FF_URL}" -o /tmp/ffmpeg.tar.xz; \
    tar -xJf /tmp/ffmpeg.tar.xz --strip-components=2 -C /usr/local/bin/ --wildcards '*/bin/ffmpeg' '*/bin/ffprobe'; \
    rm -f /tmp/ffmpeg.tar.xz; \
    chmod +x /usr/local/bin/ffmpeg /usr/local/bin/ffprobe; \
    apt-get purge -y curl xz-utils && apt-get autoremove -y; \
    rm -rf /var/lib/apt/lists/*; \
    echo "ffmpeg installed:"; ffmpeg -version 2>&1 | head -1; \
    echo "VMAF filter:"; (ffmpeg -filters 2>&1 | grep libvmaf || echo "NOT FOUND")

# Record lineage so the running backend's Monitor page knows exactly which
# ffmpeg build the image shipped with.
ENV SHRINKERR_FFMPEG_BUILD=${FFMPEG_BUILD}
# This image has no CUDA runtime, so NVENC is structurally unavailable.
# Backend detection (backend/nodes.py) will notice no NVIDIA GPU + no
# nvidia-smi and advertise only libx265. Flag it here too so the UI can
# explain "this image is CPU-only by design" rather than "your driver's
# too old" to users pulling :latest without realising :nvenc exists.
ENV SHRINKERR_CPU_ONLY_IMAGE=1

WORKDIR /app

COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

COPY backend/ backend/
COPY VERSION .
# CHANGELOG is read at runtime by /api/stats/changelog so the Updates
# section in Settings can show release notes without a network call.
COPY CHANGELOG.md .
COPY --from=frontend-build /app/frontend/dist frontend/dist

RUN mkdir -p /app/data

EXPOSE 6680

# Bundled TMDB non-commercial API key — passed in at build time from the
# TMDB_API_KEY GitHub Actions secret so the image ships with a working
# default. User-saved keys in Settings always win (see
# backend/metadata.py::resolve_tmdb_key). Builds without the secret set
# leave this empty and behave as before.
ARG TMDB_API_KEY=""
ENV SHRINKERR_TMDB_API_KEY=${TMDB_API_KEY}

HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
  CMD python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:6680/api/health')" || exit 1

# SHRINKERR_MODE=worker → run as a remote worker node (no server, no UI).
# Default → run the FastAPI server + UI.
CMD ["python3", "-m", "backend.main"]