# nbdmux container -- bundles the daemon + nbdkit + minimal Python.
#
# Build:  podman build -t ghcr.io/safl/nbdmux:dev -f deploy/Containerfile .
# Run:    see deploy/compose.yml for the production shape.
#
# Two ports:
#   8082   HTTP control plane + operator UI
#  10809   NBD (nbdkit)

# Ubuntu 26.04 for nbdkit >= 1.44, which is when the ``cow`` filter
# became safe to combine with per-connection named exports (see the
# "Export safe" column in the nbdkit-filter-cow(1) man page). Debian
# trixie ships 1.42 in which the same combination silently corrupts.
# nbdmux depends on cow-per-export to give operators writable
# ramboot targets over read-only image blobs, so the newer nbdkit
# is a hard requirement, not an optimization.
FROM ubuntu:26.04

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
        nbdkit \
        python3 \
        python3-pip \
        ca-certificates \
        curl \
        gzip \
        zstd \
        xz-utils \
 && rm -rf /var/lib/apt/lists/*

# curl: HEALTHCHECK below. curl's ``-f`` treats any 4xx/5xx as a
# non-zero exit without dumping a Python Traceback into
# ``podman logs`` on every probe when /healthz returns 503
# (nbdkit down). The Python-in-CMD alternative worked but spammed
# the logs on every failed probe.

# gzip / zstd / xz-utils: the Warmer pipeline pipes upstream bytes
# through ``gunzip -c`` / ``zstd -d -c`` / ``xz -d -c`` while
# streaming into the decompressed .img on disk. On Ubuntu 26.04 we
# pin them explicitly rather than relying on the base having them.

WORKDIR /app
COPY pyproject.toml README.md LICENSE /app/
COPY src/ /app/src/
RUN pip install --break-system-packages --no-cache-dir .

# Persistent state lives under /data. The compose stack binds this to a
# named volume so a container rebuild keeps registered exports.
ENV NBDMUX_DATA_DIR=/data
VOLUME ["/data"]

# Two distinct paths for .img files:
#   /images (this VOLUME, typically a host bind mount) -- pre-warmed
#     images the operator places on disk, registered via
#     POST /exports {name, file}. The daemon serves them read-only.
#   /data/images (inside the /data volume above) -- warm-created
#     images the daemon decompresses under <data-dir>/images/<name>.img
#     when the warm-via-src_url path fires. NOT visible on the /images
#     bind; a create-then-delete cycle here unlinks the .img
#     (DELETE /exports/<name> post-Pass-2).
# The daemon will serve any absolute path the operator registers; the
# split above is convention, not enforcement.
VOLUME ["/images"]

EXPOSE 8082 10809

HEALTHCHECK --interval=15s --timeout=3s --start-period=5s \
    CMD curl -fsS -o /dev/null --max-time 2 http://localhost:8082/healthz || exit 1

ENTRYPOINT ["nbdmux-server"]
CMD ["--data-dir", "/data", "--port", "8082", "--nbd-port", "10809"]
