# syntax=docker/dockerfile:1.7
# hvac container image.
#
# Two-stage build:
#   1. builder — Debian + Rust, compiles the release binary from this repo.
#   2. runtime — Debian-slim + ffmpeg + the VAAPI userland. The binary is
#                copied in, no toolchain in the final image.
#
# Why Debian and not Alpine? hvac transitively depends on glibc-only
# crates (the LaunchDarkly SDK pulls in `ring`), and the Debian apt
# ffmpeg ships every encoder hvac drives — Alpine's ffmpeg is missing
# `hevc_nvenc` and the VAAPI driver story on musl is fragile enough
# that a single-platform image is the better trade.
#
# NVIDIA support: this image does NOT bundle the NVIDIA userspace
# driver. Use `--gpus all --runtime=nvidia` (nvidia-container-toolkit on
# the host) to inject it at run time. That's the standard pattern and
# keeps the image size in the low hundreds of MB rather than ~2 GB.
#
# Build:
#   docker build -t ghcr.io/jackdanger/hvac:dev .
#
# Run (Intel iGPU):
#   docker run --rm --device /dev/dri:/dev/dri \
#     -v /path/to/media:/media \
#     ghcr.io/jackdanger/hvac:dev --dry-run /media
#
# Run (NVIDIA):
#   docker run --rm --gpus all --runtime=nvidia \
#     -v /path/to/media:/media \
#     ghcr.io/jackdanger/hvac:dev --dry-run /media

# ---- builder ----------------------------------------------------------------

FROM rust:1.93-bookworm AS builder

WORKDIR /src
# Copy the manifests first so `cargo fetch` is cached when only sources change.
COPY Cargo.toml Cargo.lock ./
# Touch a stub main so `cargo fetch` resolves without the real sources.
RUN mkdir -p src && echo "fn main(){}" > src/main.rs && \
    cargo fetch --locked && \
    rm -rf src
COPY . .
RUN cargo build --release --locked && \
    strip target/release/hvac

# ---- runtime ----------------------------------------------------------------

FROM debian:bookworm-slim AS runtime

# ffmpeg                  — the encoders hvac drives.
# vainfo + libva-drm2     — VAAPI diagnostics + the run-time userland.
# intel-media-va-driver   — Broadwell+ Intel iGPUs (amd64 only; no arm64
#                           candidate, so we add it conditionally below).
# mesa-va-drivers         — older Intel + AMD.
# ca-certificates         — LaunchDarkly + OTel exporter use HTTPS.
# tini                    — PID 1, forwards signals so Ctrl-C cancels cleanly
#                           rather than getting eaten by Docker's default init.
#
# TARGETARCH is set automatically by buildx in multi-platform builds. It
# resolves to "amd64" / "arm64" / etc — the same names apt uses. We gate
# intel-media-va-driver on amd64 because the package literally does not
# exist on arm64 (it ships Intel-specific shaders) and an unconditional
# install bricks the arm64 image build.
ARG TARGETARCH
RUN set -eux; \
    extra=""; \
    if [ "${TARGETARCH:-amd64}" = "amd64" ]; then \
        extra="intel-media-va-driver"; \
    fi; \
    apt-get update; \
    # shellcheck disable=SC2086
    apt-get install -y --no-install-recommends \
        ffmpeg \
        vainfo \
        libva-drm2 \
        mesa-va-drivers \
        ca-certificates \
        tini \
        $extra; \
    rm -rf /var/lib/apt/lists/*

COPY --from=builder /src/target/release/hvac /usr/local/bin/hvac

# Match the typical NAS admin UID/GID so files written back to bind-mounts
# don't end up root-owned. GID 100 is the pre-existing "users" group on
# Debian (and on Synology / Unraid / OMV — the value was chosen because
# their admin accounts already sit there), so we just reuse it rather
# than create a parallel "hvac" group at the same number.
# Override with `--user $(id -u):$(id -g)` if your NAS uses different values.
#
# Order matters: create /media + chown it as root, *then* switch to the
# unprivileged user. WORKDIR after USER would try to mkdir as that user
# and fail on the root-owned parent. The bind mount at runtime hides
# this directory anyway, but the entrypoint still runs from it when
# no mount is provided (e.g. `docker run hvac --help`).
RUN useradd -m -u 1026 -g 100 hvac && mkdir -p /media && chown hvac:users /media
WORKDIR /media
USER hvac:users

ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/hvac"]
CMD ["--help"]
