thox-mesh-node / Dockerfile
tommytracx's picture
v1.1.0: CPU-safe GPU detection, real GPU offload, hardened fallible calls, doctor command
dc03fa5 verified
Raw
History Blame Contribute Delete
4.11 kB
# THOX Mesh Node β€” free CPU Space image.
#
# Two-stage: llama-cpp-python is compiled in a builder that has a toolchain, and
# only the resulting wheel is carried into the slim runtime. That keeps gcc,
# cmake and the 64 MB source tarball out of the shipped image.
#
# Why compile at all: llama-cpp-python publishes no manylinux wheel on PyPI, and
# the project's CPU wheel index carries nothing newer than 0.1.30 for cp311. A
# plain `pip install` therefore falls back to the sdist and dies on
# "CMAKE_C_COMPILER not set" in a slim base. Compiling is the supported path.
#
# ThoxLLM-327M-v2 has `architectures: null` in its config, so transformers'
# AutoModel cannot load it β€” GGUF via llama.cpp is the only way to serve this
# model, which is why the build is worth doing rather than routed around.
# Base is pinned to bookworm (Debian 12 / gcc 12) on BOTH stages, for two reasons:
# trixie's gcc 14 refuses to compile this llama.cpp's ggml-cpu-aarch64.cpp
# ("invalid conversion from const ggml_half*", -fpermissive), and a builder on a
# newer glibc than the runtime produces a wheel the runtime cannot load.
#
# ── builder ──────────────────────────────────────────────────────────────
FROM python:3.11-slim-bookworm AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends build-essential cmake ninja-build git \
&& rm -rf /var/lib/apt/lists/*
# GGML_NATIVE=OFF is load-bearing, not tidiness. With it on, ggml compiles for
# the *builder's* CPU and can emit AVX-512 that the Space's runtime CPU does not
# implement β€” the binary then dies with SIGILL at model load, long after the
# build looked green. Off gives a portable baseline build.
#
# Nothing beyond NATIVE is overridden. An earlier attempt set AVX2=ON with
# FMA=OFF, which is self-contradictory: ggml's AVX2 kernels call
# _mm256_fmadd_ps, and gcc then fails with "inlining failed in call to
# always_inline _mm256_fmadd_ps: target specific option mismatch". ggml's own
# defaults (AVX/AVX2/FMA/F16C on, AVX-512 off) are coherent and portable across
# every x86 host Spaces run on.
ENV CMAKE_ARGS="-DGGML_NATIVE=OFF -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_EXAMPLES=OFF" \
FORCE_CMAKE=1
RUN pip install --no-cache-dir --upgrade pip wheel setuptools scikit-build-core
RUN pip wheel --no-cache-dir --wheel-dir /wheels llama-cpp-python==0.3.5
# ── runtime ──────────────────────────────────────────────────────────────
FROM python:3.11-slim-bookworm
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
# HF mounts a writable /data only on paid tiers; keep caches under /tmp.
HF_HOME=/tmp/hf \
XDG_CACHE_HOME=/tmp/cache
# libgomp1 is REQUIRED, not optional. ggml builds with OpenMP, so libllama.so
# links libgomp.so.1; that library ships with gcc in the builder but not in the
# slim runtime. Without it the image builds and starts, then dies at model load
# with "libgomp.so.1: cannot open shared object file" β€” a failure no build-time
# check catches, only actually running the thing.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl libgomp1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /wheels /wheels
COPY space/requirements.txt /app/requirements.txt
# --find-links prefers the wheel we just built; nothing else needs compiling.
RUN pip install --no-cache-dir --find-links /wheels -r /app/requirements.txt \
&& rm -rf /wheels
COPY thoxmesh_node /app/thoxmesh_node
COPY space/app.py /app/app.py
RUN useradd -m -u 1000 thox && mkdir -p /tmp/hf /tmp/cache && chown -R thox /app /tmp/hf /tmp/cache
USER thox
EXPOSE 7860
# start-period is generous: first boot downloads the GGUF before it can serve.
HEALTHCHECK --interval=30s --timeout=10s --start-period=420s --retries=5 \
CMD curl -fsS http://127.0.0.1:7860/health || exit 1
CMD ["python", "/app/app.py"]