Hunyuan3D 2.1 in Docker on Nvidia DGX Spark
Nvidia DGX Spark is a compact GPU workstation. In this article I share my hands‑on notes about the device and show how to run Hunyuan3D 2.1 in Docker on this platform.
But first, a short preface.
Why DGX Spark?¶
Since Apple switched to Apple Silicon, I moved from Windows to macOS entirely. Apple chips use unified memory architecture (UMA) — CPU and GPU share the same memory pool, up to 128 GB. However, most AI software targets CUDA, and not everything runs on Mac because many libraries aren’t ported to Metal yet.
DGX Spark is not a replacement for a MacBook, it’s a companion. The module offloads AI/ML work that depends on CUDA libraries without taxing the main machine.
Price, briefly¶
Is it worth the money? It’s definitely not cheap. My configuration cost €4180 delivered to Spain within a few days. But let’s compare it to Windows alternatives (prices in Spain as of November 30, 2025, rounded from online stores):
- PNY RTX PRO 6000 Blackwell (96 GB GDDR7) — about €8500
- Nvidia RTX PRO 5000 Blackwell (48 GB GDDR7) — about €5500
At around €4000, DGX Spark with full CUDA support looks like a reasonable compromise. I’d been waiting for this device since March 2025 — and I’m not disappointed.
DGX Spark build specifics¶
Running Hunyuan3D 2.1 on DGX Spark has a few technical caveats:
- Python version. DGX Spark ships with a newer Python, but Hunyuan3D 2.1 (and Blender) require Python 3.10. Deadsnakes packages didn’t work here, so I built Python 3.10.19 from source.
- ARM architecture. DGX Spark is ARM‑based, and some libraries don’t provide ready‑made wheels. In particular, the Blender Python API (bpy) must be built manually.
- Dependency hell. To smooth things out, I use a small fork of Hunyuan3D 2.1 where only requirements.txt is adjusted.
All of this can be done without Docker, installing dependencies directly on the host. I don’t recommend that approach — you’ll need a lot of packages and may run into conflicts.
Docker Compose¶
The Compose configuration is simple. It maps port 7860 for the Gradio UI and gives the container access to all GPUs:
services:
hy3d:
build: .
container_name: hy3d
ports:
- "7860:7860"
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
environment:
NVIDIA_VISIBLE_DEVICES: all
NVIDIA_DRIVER_CAPABILITIES: compute,utility
working_dir: /workspace/Hunyuan3D-2.1
tty: true
stdin_open: true
After launching, the UI will be available at http://spark-XXNN.local:7860/ (replace XXNN with your DGX Spark ID).
Building the image step by step¶
Base image¶
Use Nvidia’s official CUDA image with CUDA 13.0 and Ubuntu 24.04:
The nvcr.io/nvidia/cuda:13.0.1-devel-ubuntu24.04 image ships with the CUDA toolkit and development tools. DEBIAN_FRONTEND=noninteractive disables interactive prompts during package installation.
Dependencies for building Python¶
Install the basics required to build Python 3.10.19 from source:
apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates curl wget build-essential \
libssl-dev zlib1g-dev libbz2-dev libsqlite3-dev libffi-dev liblzma-dev \
&& rm -rf /var/lib/apt/lists/*
These libraries provide SSL, compression and other core Python features. They are needed both for Hunyuan and for building bpy.
OpenGL and X11 libraries¶
For 3D workflows and headless rendering, install OpenGL and X11. The QT_QPA_PLATFORM=offscreen env variable forces Qt to run headless:
apt-get update && apt-get install -y --no-install-recommends \
libopengl0 libgl1 libglx0 libglu1-mesa \
libx11-6 libxext6 libxrender1 libxi6 \
libxxf86vm1 libxfixes3 libxkbcommon0 libxcb1 \
&& rm -rf /var/lib/apt/lists/*
ENV QT_QPA_PLATFORM=offscreen
Build Python 3.10.19¶
Download and build Python 3.10.19 with optimizations:
cd /opt
wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tgz
tar -xvf Python-3.10.19.tgz
cd Python-3.10.19
./configure --enable-optimizations
make -j"$(nproc)"
make altinstall
make altinstall places Python at /usr/local/bin/python3.10 without overwriting the system Python. Cleanup afterwards:
Virtual environment¶
Create a venv at /opt/py310, upgrade pip, and make that venv the default binary path:
/usr/local/bin/python3.10 -m venv /opt/py310
/opt/py310/bin/python -m ensurepip --upgrade
/opt/py310/bin/python -m pip install --upgrade pip setuptools wheel
ENV PATH="/opt/py310/bin:${PATH}"
Blender dependencies¶
Blender needs quite a few libraries for audio, images, and 3D:
apt-get update && apt-get install -y --no-install-recommends \
cmake autoconf automake bison libtool yasm tcl ninja-build meson patchelf \
libopenal-dev libsndfile1-dev libjack-dev libpulse-dev \
libjpeg-dev libpng-dev libtiff-dev libopenexr-dev \
libepoxy-dev libfreetype6-dev libopenimageio-dev libboost-all-dev \
pkg-config libpugixml-dev libfftw3-dev \
libembree-dev libvulkan-dev libshaderc-dev \
libglib2.0-dev libcurl4-openssl-dev subversion \
&& rm -rf /var/lib/apt/lists/*
Before building Blender, install NumPy — it’s required for generating the Python API:
Build the Blender Python API¶
Clone Blender v4.0.2:
mkdir -p /workspace/blender_dev
cd /workspace/blender_dev
git clone https://projects.blender.org/blender/blender.git
cd blender
git fetch --all --tags
git checkout v4.0.2
git submodule update --init --recursive
Configure the CMake build to produce a Python module (no GUI):
mkdir -p /workspace/blender_dev/build_bpy
cd /workspace/blender_dev/build_bpy
cmake ../blender \
-DWITH_PYTHON_MODULE=ON \
-DWITH_PYTHON_INSTALL=OFF \
-DWITH_HEADLESS=ON \
-DWITH_OPENAL=OFF \
-DWITH_LIBS_PRECOMPILED=OFF \
-DWITH_SYSTEM_GLIB=ON \
-DWITH_SYSTEM_CURL=ON \
-DPYTHON_EXECUTABLE=/opt/py310/bin/python \
-DCMAKE_BUILD_TYPE=Release
make -j"$(nproc)"
Key flags: - WITH_PYTHON_MODULE=ON — build bpy as a Python module - WITH_HEADLESS=ON — no GUI - PYTHON_EXECUTABLE — points to our Python 3.10
Add bpy to PYTHONPATH:
ENV BLENDER_SYSTEM_SCRIPTS="/workspace/blender_dev/blender/scripts"
ENV BLENDER_SYSTEM_DATAFILES="/workspace/blender_dev/blender/release/datafiles"
ENV PYTHONPATH="${PYTHONPATH}:/workspace/blender_dev/build_bpy/bin"
Clone the project¶
Clone the Hunyuan3D 2.1 fork with dependency fixes; or fix them yourself. I removed version pins for pymeshlab and xatlas (there’s only one available anyway), and removed bpy because we build it ourselves.
Install PyTorch¶
Install PyTorch built for CUDA 13.0:
Speed up Hugging Face model downloads with hf_xet:
Project dependencies¶
This part mirrors the instructions in the original repository. Install the rest from requirements.txt:
CUDA setup¶
Create a python3-config symlink required by CUDA extensions. Without this, the differentiable renderer won’t compile:
CUDA environment variables:
ENV CUDA_HOME=/usr/local/cuda-13.0
ENV PATH="$CUDA_HOME/bin:${PATH}"
ENV LD_LIBRARY_PATH="$CUDA_HOME/lib64:${LD_LIBRARY_PATH}"
ENV TORCH_CUDA_ARCH_LIST="12.1+PTX"
TORCH_CUDA_ARCH_LIST="12.1+PTX" specifies target GPU architectures for compiling CUDA code. If you build outside Docker, you may not need to set this manually — the architecture can be detected automatically.
Compile CUDA modules¶
Build the custom rasterizer:
Compile the differentiable renderer:
Download ESRGAN weights¶
Grab the pre‑trained weights for texture upscaling:
mkdir -p hy3dpaint/ckpt
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P hy3dpaint/ckpt
Run the app¶
Expose the Gradio UI port:
Start the application with a few libraries preloaded for aarch64:
LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0:/usr/lib/aarch64-linux-gnu/libcurl.so.4:/usr/lib/aarch64-linux-gnu/libnghttp2.so.14" \
python gradio_app.py --host 0.0.0.0 --port 7860
LD_PRELOAD works around dependency loading issues. It’s a bit of a workaround, yes. Blender was built against one set of libraries while the rasterizer was built against another.
Final Dockerfile¶
Here’s the complete Dockerfile with all steps:
FROM nvcr.io/nvidia/cuda:13.0.1-devel-ubuntu24.04
ARG DEBIAN_FRONTEND=noninteractive
# PYTHON SETUP
## 1) Install build dependencies for Python 3.10.19 and helper utilities
RUN apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates curl wget build-essential \
libssl-dev zlib1g-dev libbz2-dev libsqlite3-dev libffi-dev liblzma-dev \
&& rm -rf /var/lib/apt/lists/*
## 2) OpenGL/X11 libraries required for pymesh3d (PLY) and headless rendering
# Note: For arm64 (aarch64) Ubuntu/Debian, package names are the same.
RUN apt-get update && apt-get install -y --no-install-recommends \
libopengl0 \
libgl1 \
libglx0 \
libglu1-mesa \
libx11-6 \
libxext6 \
libxrender1 \
libxi6 \
libxxf86vm1 \
libxfixes3 \
libxkbcommon0 \
libxcb1 \
&& rm -rf /var/lib/apt/lists/*
ENV QT_QPA_PLATFORM=offscreen
## 3) Build and install Python 3.10.19 from source (altinstall -> /usr/local/bin/python3.10)
# Reason: Blender build and Hunyuan3D 2.1 target Python 3.10.
RUN set -eux; \
cd /opt; \
wget https://www.python.org/ftp/python/3.10.19/Python-3.10.19.tgz; \
tar -xvf Python-3.10.19.tgz; \
cd Python-3.10.19; \
./configure --enable-optimizations; \
make -j"$(nproc)"; \
make altinstall; \
/usr/local/bin/python3.10 --version; \
cd /; \
rm -rf /opt/Python-3.10.19 /opt/Python-3.10.19.tgz
## 4) Install NumPy (required to build Blender/bpy)
RUN /usr/local/bin/python3.10 -m pip install --no-cache-dir numpy
## 5) Create a virtual environment and upgrade pip/setuptools/wheel
RUN /usr/local/bin/python3.10 -m venv /opt/py310 \
&& /opt/py310/bin/python -m ensurepip --upgrade \
&& /opt/py310/bin/python -m pip install --upgrade pip setuptools wheel
## 6) Use the virtual environment (/opt/py310) by default
ENV PATH="/opt/py310/bin:${PATH}"
# BLENDER BUILD
## 1) Install packages for building Blender and its dependencies
RUN rm -rf /var/lib/apt/lists/* \
&& apt-get update -o Acquire::Retries=5 -o Acquire::http::No-Cache=true \
&& apt-get -y upgrade \
&& apt-get install -y --no-install-recommends \
cmake autoconf automake bison libtool yasm tcl ninja-build meson patchelf \
libopenal-dev libsndfile1-dev libjack-dev libpulse-dev \
libjpeg-dev libpng-dev libtiff-dev libopenexr-dev \
libepoxy-dev libfreetype6-dev \
libopenimageio-dev libboost-all-dev \
pkg-config libpugixml-dev libfftw3-dev \
libembree-dev libvulkan-dev libshaderc-dev \
libglib2.0-dev libcurl4-openssl-dev \
subversion \
&& rm -rf /var/lib/apt/lists/*
## 2) Install NumPy in the current venv (headers required to build bpy)
RUN pip install --no-cache-dir numpy
## 3) Clone Blender 4.0.2 and initialize submodules
RUN mkdir -p /workspace/blender_dev \
&& cd /workspace/blender_dev \
&& git clone https://projects.blender.org/blender/blender.git \
&& cd blender \
&& git fetch --all --tags \
&& git checkout v4.0.2 \
&& git submodule update --init --recursive
## 4) Build bpy (headless) using Python 3.10 from the venv
## Debug tip: verbose output is enabled; for troubleshooting, rebuild with make -j1 to surface the first real error.
RUN mkdir -p /workspace/blender_dev/build_bpy \
&& cd /workspace/blender_dev/build_bpy \
&& cmake ../blender \
-DWITH_PYTHON_MODULE=ON \
-DWITH_PYTHON_INSTALL=OFF \
-DWITH_HEADLESS=ON \
-DWITH_OPENAL=OFF \
-DWITH_LIBS_PRECOMPILED=OFF \
-DWITH_SYSTEM_GLIB=ON \
-DWITH_SYSTEM_CURL=ON \
-DPYTHON_EXECUTABLE=/opt/py310/bin/python \
-DCMAKE_VERBOSE_MAKEFILE=ON \
-DCMAKE_BUILD_TYPE=Release \
&& make -j"$(nproc)"
## 5) Make bpy available in all container sessions
ENV BLENDER_SYSTEM_SCRIPTS="/workspace/blender_dev/blender/scripts"
ENV BLENDER_SYSTEM_DATAFILES="/workspace/blender_dev/blender/release/datafiles"
ENV PYTHONPATH="${PYTHONPATH}:/workspace/blender_dev/build_bpy/bin"
# END OF BLENDER BUILD
# PROJECT SETUP AND BUILD
## 1) Clone the repository (DGX fork)
RUN git clone -b DGX-Spark https://github.com/dr-vij/Hunyuan3D-2.1-DGX /workspace/Hunyuan3D-2.1
WORKDIR /workspace/Hunyuan3D-2.1
## 2) Install Python dependencies (PyTorch CUDA 13.0 build first)
RUN pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130
## 3) Speed up model downloads (Hugging Face with xet)
RUN pip install --no-cache-dir -U "huggingface_hub[hf_xet]"
## 4) Install project dependencies
RUN pip install -r requirements.txt
## 5) Ensure python3-config symlink in the venv (required for custom_rasterizer/DifferentiableRenderer)
# Create/update: /opt/py310/bin/python3-config -> /usr/local/bin/python3.10-config
RUN ln -sf /usr/local/bin/python3.10-config /opt/py310/bin/python3-config
## 6) Set CUDA environment (adjust CUDA version and arch as needed)
# DGX Spark uses CUDA 13.0 and arch "12.1+PTX".
ENV CUDA_HOME=/usr/local/cuda-13.0
ENV PATH="$CUDA_HOME/bin:${PATH}"
ENV LD_LIBRARY_PATH="$CUDA_HOME/lib64:${LD_LIBRARY_PATH}"
ENV TORCH_CUDA_ARCH_LIST="12.1+PTX"
## 7) Build and install hy3dpaint custom rasterizer
RUN bash -lc "cd hy3dpaint/custom_rasterizer && pip install -e . --no-build-isolation"
## Note: If this fails, verify that python3.10-config is correct.
## 8) Compile the differentiable renderer
RUN bash -lc "cd hy3dpaint/DifferentiableRenderer && bash compile_mesh_painter.sh"
## 9) Download ESRGAN weights
RUN mkdir -p hy3dpaint/ckpt \
&& wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P hy3dpaint/ckpt
# RUNTIME
## 1) Expose port for the Gradio UI
# You can connect to your Spark later via http://spark-XXNN.local:7860/ (replace XXNN with your Spark ID)
EXPOSE 7860
## 2) Start the Gradio application on container startup
# Assumes gradio_app.py is located at /workspace/Hunyuan3D-2.1
# LD_PRELOAD is added for correct dependency loading on aarch64
CMD bash -lc "cd /workspace/Hunyuan3D-2.1 && \
LD_PRELOAD=\"/usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0:/usr/lib/aarch64-linux-gnu/libcurl.so.4:/usr/lib/aarch64-linux-gnu/libnghttp2.so.14\" \
python gradio_app.py --host 0.0.0.0 --port 7860"
# I spent 8+ hours setting this up, with help from Google Search and JetBrains Junie
LABEL authors="dr-vij (Viktor Grigorev)"
Build and start the container:
Open the UI in your browser: http://spark-XXNN.local:7860/ (replace XXNN with your Spark ID)
Links¶
Full code, including Docker Compose and Dockerfile, is available here: Hunyuan3D-2.1-DGX-Docker