Перейти к содержанию

Hunyuan3D 2.1 внутри Docker на Nvidia DGX Spark

Nvidia DGX Spark — компактная рабочая станция с GPU. В этой статье я расскажу о своём опыте работы с этой железкой и покажу, как запустить Hunyuan3D 2.1 в Docker на этой платформе.

Но сначала короткое вступление.

Почему DGX Spark?

С момента перехода Apple на процессоры Apple Silicon я полностью переключился с Windows на macOS. Чипы Apple используют унифицированную архитектуру памяти (UMA) — CPU и GPU работают с общей памятью до 128 ГБ. Однако большая часть AI-софта написана под CUDA, и не всё удаётся запустить на Mac, поскольку не все библиотеки портированы под Metal.

DGX Spark — это не замена MacBook, а дополнение. Модуль берёт на себя задачи AI/ML с CUDA-зависимыми библиотеками, не расходуя ресурсы основной машины.

Вопрос цены

Стоит ли это своих денег? Безусловно, это недешёвое решение. Моя конфигурация обошлась в €4180 с доставкой в Испанию за несколько дней. Но давайте сравним с альтернативами на Windows (цены в Испании на 30 ноября 2025 года из интернет-магазинов, округлены):

  • PNY RTX PRO 6000 Blackwell (96 ГБ GDDR7) — около €8500
  • Nvidia RTX PRO 5000 Blackwell (48 ГБ GDDR7) — около €5500

DGX Spark за €4000 с полноценной поддержкой CUDA выглядит разумным компромиссом. Я ждал эту железку с марта 2025 года — и не разочаровался.

Особенности сборки на DGX Spark

Запуск Hunyuan3D 2.1 на DGX Spark сопряжён с несколькими техническими особенностями:

  1. Версия Python. DGX Spark поставляется с новой версией Python, но Hunyuan3D 2.1 (и Blender) требуют Python 3.10. Пакеты из deadsnakes не подошли, поэтому пришлось собирать Python 3.10.19 из исходников.

  2. ARM-архитектура. DGX Spark использует ARM-процессор, и для некоторых библиотек нет готовых wheel-пакетов. В частности, Blender Python API (bpy) необходимо собирать вручную.

  3. Dependency hell. Для решения проблем с зависимостями я использую небольшой форк Hunyuan3D 2.1, в котором изменены только requirements.txt.

Всё это можно делать без Docker, устанавливая зависимости прямо в систему. Я не рекомендую этот путь — придётся установить большое количество пакетов, что может привести к конфликтам.

Docker Compose

Конфигурация Docker Compose проста. Она пробрасывает порт 7860 для Gradio UI и предоставляет контейнеру доступ ко всем GPU:

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

После запуска интерфейс будет доступен по адресу http://spark-XXNN.local:7860/ (где XXNN — идентификатор вашего DGX Spark).

Пошаговая сборка образа

Базовый образ

Для работы с CUDA используем официальный образ Nvidia с CUDA 13.0 и Ubuntu 24.04:

FROM nvcr.io/nvidia/cuda:13.0.1-devel-ubuntu24.04
ARG DEBIAN_FRONTEND=noninteractive

Образ nvcr.io/nvidia/cuda:13.0.1-devel-ubuntu24.04 содержит CUDA toolkit и development-инструменты. DEBIAN_FRONTEND=noninteractive отключает интерактивные запросы при установке пакетов.

Зависимости для сборки Python

Устанавливаем базовые инструменты и библиотеки, необходимые для сборки Python 3.10.19 из исходников:

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/*

Эти библиотеки обеспечивают поддержку SSL, сжатия и других базовых функций Python. Они необходимы для работы Hunyuan и сборки bpy.

Библиотеки для OpenGL и X11

Для работы с 3D-моделями и headless-рендеринга устанавливаем OpenGL и X11, переменная окружения QT_QPA_PLATFORM=offscreen переключает Qt в режим без графического интерфейса:

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

Сборка Python 3.10.19

Загружаем исходники Python 3.10.19 и собираем с оптимизациями:

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 устанавливает Python в /usr/local/bin/python3.10 без перезаписи системного Python. После установки очищаем временные файлы:

rm -rf /opt/Python-3.10.19 /opt/Python-3.10.19.tgz

Виртуальное окружение

Создаём виртуальное окружение в /opt/py310 и обновляем pip, Делаем это окружение окружением по умолчанию:

/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

Blender требует множество библиотек для работы с аудио, изображениями и 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/*

Перед сборкой Blender устанавливаем NumPy — он нужен для генерации Python API:

pip install --no-cache-dir numpy

Сборка Blender Python API

Клонируем репозиторий Blender версии 4.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

Конфигурируем сборку через CMake для создания Python-модуля без 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)"

Ключевые параметры: - WITH_PYTHON_MODULE=ON — собираем bpy как Python-модуль - WITH_HEADLESS=ON — без GUI - PYTHON_EXECUTABLE — указываем путь к нашему Python 3.10

Добавляем bpy в 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"

Клонирование проекта

Клонируем форк Hunyuan3D 2.1 с исправленными зависимостями, либо можете исправить зависимости сами я убрал версию у pymeshlab и xatlas, там доступна единственная версия, не та что в оригинале. А также убрал bpy тк мы его будем собирать сами.

git clone -b DGX-Spark https://github.com/dr-vij/Hunyuan3D-2.1-DGX /workspace/Hunyuan3D-2.1
WORKDIR /workspace/Hunyuan3D-2.1

Установка PyTorch

Устанавливаем PyTorch с поддержкой CUDA 13.0:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu130

Для ускорения загрузки моделей с Hugging Face используем расширение hf_xet:

pip install --no-cache-dir -U "huggingface_hub[hf_xet]"

Зависимости проекта

Далее все похоже на инструкцию в репозитории. Устанавливаем остальные зависимости из requirements.txt:

pip install -r requirements.txt

Настройка CUDA

Создаём симлинк на python3-config, необходимый для компиляции CUDA-расширений. Это важный шаг, без него differentiable renderer не собертся:

ln -sf /usr/local/bin/python3.10-config /opt/py310/bin/python3-config

Настраиваем переменные окружения для CUDA:

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" указывает архитектуру GPU для компиляции CUDA-кода. Если собираете без докера - вам это не понадобится, тк архитектура определится автоматически

Компиляция CUDA-модулей

Собираем custom rasterizer:

cd hy3dpaint/custom_rasterizer && pip install -e . --no-build-isolation

Компилируем differentiable renderer:

cd hy3dpaint/DifferentiableRenderer && bash compile_mesh_painter.sh

Загрузка весов ESRGAN

Загружаем предобученные веса для апскейлинга текстур:

mkdir -p hy3dpaint/ckpt
wget https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P hy3dpaint/ckpt

Запуск приложения

Пробрасываем порт для Gradio UI:

EXPOSE 7860

Запускаем приложение с предзагрузкой необходимых библиотек для ARM-архитектуры:

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 решает проблемы с загрузкой зависимостей. Это костыль, как и многое другое в этом гайде. Но избавиться от него у меня пока не получилось. Когда мы собирали блендер он использовал одну версию либ, а растеризатор другую.

Итоговый Dockerfile

Полный Dockerfile со всеми шагами:

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)"

Соберите и запустите контейнер:

docker compose up --build

Откройте интерфейс в браузере: http://spark-XXNN.local:7860/ (замените XXNN на ваш Spark ID)

Ссылки

Полный код, включая Docker Compose и Dockerfile, доступен в репозитории: Hunyuan3D-2.1-DGX-Docker