ARG DEBIAN_VERSION=stable-slim ARG YTDLP_REPO="yt-dlp/yt-dlp" # Stage 1: Runtime FROM debian:${DEBIAN_VERSION} AS base RUN apt-get update && apt-get install -y --no-install-recommends \ ffmpeg python3 python3-pip curl ca-certificates unzip \ && rm -rf /var/lib/apt/lists/* # Install yt-dlp and its dependencies via pip so they share the SAME # curl_cffi instance. The standalone release binary bundles its own older # curl_cffi which lacks modern impersonation profiles like chrome131, # safari18_0, firefox135, etc. Installing via pip ensures the same profile # set is available to both the scrape step and yt-dlp. RUN pip install --no-cache-dir --break-system-packages \ "curl-cffi>=0.13.0" requests PySocks \ "yt-dlp>=2025.1.1" \ yt-dlp-get-pot bgutil-ytdlp-pot-provider # Stage 2: Fetcher (Deno only — needed as JS runtime for yt-dlp) FROM alpine:latest AS fetcher ARG TARGETARCH RUN apk add --no-cache curl unzip ARG CACHE_BUST=1 RUN DETECTED_ARCH="${TARGETARCH:-$(uname -m)}" && \ if [ "$DETECTED_ARCH" = "amd64" ] || [ "$DETECTED_ARCH" = "x86_64" ]; then \ D_ARCH="x86_64"; \ else \ D_ARCH="aarch64"; \ fi && \ curl -fsSL "https://github.com/denoland/deno/releases/latest/download/deno-${D_ARCH}-unknown-linux-gnu.zip" -o /deno.zip && \ unzip /deno.zip -d / && chmod a+rx /deno # Stage 3: Final FROM base AS final COPY --from=fetcher /deno /usr/local/bin/deno ENV XDG_CONFIG_HOME=/dev/shm/yt-dlp/config ENV XDG_CACHE_HOME=/dev/shm/yt-dlp/cache