Dockerfile.worker-cpu-only
Rama dev · réplica de lectura del repositorio original.
# VLog Remote Transcoding Worker (CPU-only)
# Containerized worker for distributed video transcoding
#
# Build: docker build -f Dockerfile.worker-cpu-only -t vlog-worker --build-arg CODE_VERSION=$(git rev-parse --short HEAD) .
# Run: docker run -e VLOG_WORKER_API_KEY=<key> -e VLOG_WORKER_API_URL=http://host:9002 vlog-worker
# Pin base image version for reproducible builds
# python:3.12-slim-trixie is Debian Trixie (13) based
ARG PYTHON_VERSION=3.12-slim-trixie
# Code version for worker compatibility checking
# Set this during build: docker build --build-arg CODE_VERSION=$(git rev-parse --short HEAD) ...
ARG CODE_VERSION=dev
ARG BUILD_TIMESTAMP=""
# Build the signed upstream FFmpeg release: Debian's FFmpeg is behind security fixes.
FROM python:${PYTHON_VERSION} AS ffmpeg-builder
ARG FFMPEG_VERSION=9.0.1
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
build-essential pkg-config nasm curl gnupg libx264-dev libx265-dev libsvtav1enc-dev libdav1d-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build/ffmpeg
RUN curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz \
&& curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz.asc \
&& curl -fsSLo release-key.asc https://ffmpeg.org/ffmpeg-devel.asc \
&& gpg --batch --import release-key.asc \
&& gpg --batch --status-fd 1 --verify ffmpeg-${FFMPEG_VERSION}.tar.xz.asc ffmpeg-${FFMPEG_VERSION}.tar.xz \
> signature.status \
&& grep '^\[GNUPG:\] VALIDSIG FCF986EA15E6E293A5644F10B4322F04D67658D8 ' signature.status \
&& tar xf ffmpeg-${FFMPEG_VERSION}.tar.xz --strip-components=1
# Files are downloaded by the worker API client; FFmpeg needs no network protocols.
RUN ./configure --prefix=/opt/ffmpeg --disable-shared --enable-static \
--disable-autodetect --enable-gpl --enable-libx264 --enable-libx265 --enable-libsvtav1 --enable-libdav1d \
--disable-doc --disable-ffplay --disable-debug --disable-network --disable-devices \
&& make -j4 && make install \
&& mkdir -p /opt/ffmpeg/licenses && cp COPYING.* /opt/ffmpeg/licenses/
# =============================================================================
# Stage 1: Builder - Install Python dependencies
# =============================================================================
FROM python:${PYTHON_VERSION} AS builder
# Install build dependencies for packages with C extensions (argon2-cffi)
# These are only needed in the builder stage, not runtime
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
gcc \
libffi-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Install the same dependency manifest used by the APIs and CI.
COPY pyproject.toml requirements.lock README.md ./
RUN pip3 install --no-cache-dir --prefix=/install --require-hashes -r requirements.lock
# Copy source code and install the package
COPY config.py ./
COPY code_version.py ./
COPY api/ api/
COPY worker/ worker/
COPY cli/ cli/
COPY backup/ backup/
RUN pip install --no-cache-dir --no-deps --prefix=/install .
# =============================================================================
# Stage 2: Runtime - Minimal production image
# =============================================================================
FROM python:${PYTHON_VERSION} AS runtime-files
# Runtime assembly keeps only required binaries/libraries, not the package tools.
# PostgreSQL clients support the application's backup and restore endpoints.
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
libx264-164 libx265-dev libsvtav1enc-dev libdav1d7 postgresql-client-17 \
&& rm -rf /var/lib/apt/lists/* \
&& ln -s /usr/lib/postgresql/17/bin/pg_dump /usr/local/bin/pg_dump \
&& ln -s /usr/lib/postgresql/17/bin/pg_restore /usr/local/bin/pg_restore
COPY --from=ffmpeg-builder /opt/ffmpeg/bin/ /usr/local/bin/
COPY --from=ffmpeg-builder /opt/ffmpeg/licenses/ /usr/share/doc/vlog-ffmpeg/
# Create non-root user for security
RUN useradd -m -u 1000 -s /bin/bash vlog
WORKDIR /app
# Copy installed Python packages from builder
COPY --from=builder /install /usr/local
# Copy source code
COPY --chown=vlog:vlog pyproject.toml ./
COPY --chown=vlog:vlog config.py ./
COPY --chown=vlog:vlog code_version.py ./
COPY --chown=vlog:vlog api/ api/
COPY --chown=vlog:vlog worker/ worker/
COPY --chown=vlog:vlog cli/ cli/
COPY --chown=vlog:vlog backup/ backup/
# Re-declare build args for use in this stage (args don't persist across stages)
ARG CODE_VERSION=dev
ARG BUILD_TIMESTAMP=""
# Switch to non-root user
USER vlog
# Create work directory
RUN mkdir -p /tmp/vlog-worker
# Assemble only the Python/media runtime and its shared-library closure. Keep
# Debian package provenance and licenses so scanners still inspect shipped code.
USER root
COPY scripts/assemble-worker-runtime.py /build/assemble-worker-runtime.py
RUN python /build/assemble-worker-runtime.py
FROM scratch AS runtime
COPY --from=runtime-files /runtime/ /
COPY --from=runtime-files --chown=1000:1000 /app/ /app/
COPY --from=ffmpeg-builder /opt/ffmpeg/licenses/ /usr/share/doc/vlog-ffmpeg/
ARG CODE_VERSION=dev
ARG BUILD_TIMESTAMP=""
WORKDIR /app
USER 1000:1000
ENV PATH=/usr/local/bin \
LD_LIBRARY_PATH=/usr/local/lib \
SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
LANG=C.UTF-8
# Environment variables with defaults
# VLOG_CODE_VERSION and VLOG_BUILD_TIMESTAMP are used for worker compatibility checking
ENV VLOG_WORKER_API_URL=http://vlog-worker-api:9002 \
VLOG_WORKER_WORK_DIR=/tmp/vlog-worker \
VLOG_WORKER_HEARTBEAT_INTERVAL=30 \
VLOG_WORKER_POLL_INTERVAL=10 \
VLOG_CODE_VERSION=${CODE_VERSION} \
VLOG_BUILD_TIMESTAMP=${BUILD_TIMESTAMP} \
PYTHONUNBUFFERED=1
# Health check - verify worker's health server is responding
# The worker exposes /health on port 8080 which verifies:
# - Worker process is alive
# - API connection is working
# - FFmpeg is available
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health', timeout=5)"]
# Run the remote transcoder
CMD ["python", "-m", "worker.remote_transcoder"]