This guide explains how to configure and customize the Trellis 3D Docker image build and runtime.
# Using the build script (recommended)
./scripts/build.sh
# Or using docker-compose
docker-compose build
# Or using docker directly
DOCKER_BUILDKIT=1 docker build -t trellis-box:latest .Quick start with custom configuration:
# Copy the example configuration
cp docker.env.example .env
# Edit to your preferences
nano .env
# Build and run with your configuration
docker-compose up --buildYou may also set environment variables via export and --build-arg
# Option 2: Using environment variables with the build script
CUDA_VERSION=12.2.0 PYTHON_VERSION=3.11 ./scripts/build.sh
# Option 3: Using --build-arg with docker
docker build \
--build-arg CUDA_VERSION=12.2.0 \
--build-arg PYTHON_VERSION=3.11 \
--build-arg APP_PORT=8080 \
-t trellis-box:custom .| Variable | Default | Description | Example Values |
|---|---|---|---|
CUDA_VERSION |
12.3.2 |
NVIDIA CUDA version | 12.3.2, 12.2.2, 12.1.1 |
CUDNN_VERSION |
9 |
cuDNN version | 8, 9 |
UBUNTU_VERSION |
22.04 |
Ubuntu base version | 20.04, 22.04 |
PYTHON_VERSION |
3.10 |
Python version | 3.10, 3.11 |
| Variable | Default | Description |
|---|---|---|
POETRY_VERSION |
1.8.3 |
Poetry package manager version |
TORCH_VERSION |
2.4.0 |
PyTorch version (for reference) |
KAOLIN_VERSION |
0.17.0 |
NVIDIA Kaolin library version |
KAOLIN_INDEX_URL |
https://nvidia-kaolin... |
Kaolin pip index URL |
TORCH_CUDA_ARCH_LIST |
7.0 7.5 8.0 8.6 8.9 9.0 |
GPU architectures to compile for |
| Variable | Default | Description |
|---|---|---|
APP_USER |
appuser |
Non-root user inside container |
APP_UID |
1000 |
User ID (match with host for permissions) |
APP_PORT |
8501 |
Streamlit application port |
HOST_PORT |
8501 |
Port exposed on host (compose only) |
STREAMLIT_SERVER_ADDRESS |
0.0.0.0 |
Streamlit bind address |
STREAMLIT_SERVER_HEADLESS |
true |
Run without browser auto-open |
| Variable | Default | Description |
|---|---|---|
CACHE_DIR |
/home/appuser/.cache |
Main cache directory inside container |
HF_CACHE_DIR |
/home/appuser/.cache/huggingface |
Hugging Face models cache |
REMBG_CACHE_DIR |
/home/appuser/.u2net |
Rembg background removal models |
TRELLIS_OUTPUT_DIR |
/tmp/Trellis-demo |
Generated outputs directory |
CACHE_VOLUME |
trellis-cache |
Docker volume name for main cache |
HF_CACHE_VOLUME |
huggingface-cache |
Docker volume name for HF cache |
REMBG_CACHE_VOLUME |
rembg-cache |
Docker volume name for rembg cache |
OUTPUTS_HOST_DIR |
./outputs |
Host directory for outputs (bind mount) |
| Variable | Default | Description |
|---|---|---|
CUDA_VISIBLE_DEVICES |
all |
Which GPUs to use |
GPU_COUNT |
all |
Number of GPUs to allocate |
| Variable | Default | Description |
|---|---|---|
IMAGE_NAME |
trellis-box |
Docker image name |
IMAGE_TAG |
latest |
Docker image tag |
# Set variables before running the script
export CUDA_VERSION=12.2.0
export PYTHON_VERSION=3.11
export APP_PORT=8080
./scripts/build.shOr inline:
CUDA_VERSION=12.2.0 PYTHON_VERSION=3.11 ./scripts/build.sh# Create your .env file
cp docker.env.example .env
# Edit the .env file
nano .env # or vim, code, etc.
# Build and run
docker-compose up --builddocker build \
--build-arg CUDA_VERSION=12.2.0 \
--build-arg PYTHON_VERSION=3.11 \
--build-arg APP_PORT=8080 \
-t trellis-box:custom .Modify the default values in the Dockerfile:
ARG CUDA_VERSION=12.2.0 # Change from 12.1.0
ARG PYTHON_VERSION=3.11 # Change from 3.10Your system has CUDA 12.2.2 instead of 12.3.2:
# Method A: Build script
CUDA_VERSION=12.2.2 ./scripts/build.sh
# Method B: Docker compose .env
echo "CUDA_VERSION=12.2.2" >> .env
docker-compose buildNote: Check NVIDIA CUDA Docker Hub for available versions and their support status.
Fix file permission issues by matching container UID to host UID:
# Get your user ID
MY_UID=$(id -u)
# Build with your UID
APP_UID=$MY_UID ./scripts/build.sh
# Or add to .env
echo "APP_UID=$MY_UID" >> .envYou have another service on port 8501:
# Using .env file
cat > .env << EOF
APP_PORT=8080
HOST_PORT=8080
EOF
docker-compose up --buildThen access at http://localhost:8080
Use only GPUs 0 and 1 out of 4 available:
# Add to .env
cat > .env << EOF
CUDA_VISIBLE_DEVICES=0,1
GPU_COUNT=2
EOF
docker-compose up# Development (faster rebuilds)
IMAGE_TAG=dev ./scripts/build.sh
# Production (specific version)
IMAGE_TAG=v1.0.0 ./scripts/build.sh --no-cacheFor active development with automatic code reloading:
# Use docker-compose with development override
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up --build
# Or set DEV environment variable (if your scripts support it)
DEV=true ./scripts/run.shWhat gets mounted in dev mode:
app.py- Main Streamlit application ✅ Hot-reloadablewebui/- Web UI components ✅ Hot-reloadabledocs/- Documentation files ✅ Hot-reloadableassets/- Static assets and examples ✅ Hot-reloadable
What does NOT get mounted:
trellis/- Core pipeline code (installed as Python package - rebuild required)extensions/- Compiled C++ extensions (rebuild required)
Benefits:
- ✅ Hot reloading for UI and app changes
- ✅ Faster iteration for interface development
- ✅ Debug friendly for web UI issues
- ✅ Persistent caches for models and dependencies
When to use dev mode:
- 🎨 UI/UX development - webui/ changes
- 🔧 App logic changes - app.py modifications
- 📊 Interface testing - layout and component changes
- 🐛 Debugging UI issues - Streamlit-specific problems
When to use production mode:
- ⚙️ Core algorithm changes - trellis/ package updates
- 🔧 Extension modifications - C++ code changes
- 🚀 Performance optimization - production deployment
- 📦 Minimal container size - distribution builds
Note: For changes to trellis/ or extensions/, rebuild the image even in dev mode.
Run multiple instances with separate caches:
# Instance 1: Development
cat > .env.dev << EOF
CACHE_VOLUME=trellis-dev-cache
HF_CACHE_VOLUME=huggingface-dev-cache
REMBG_CACHE_VOLUME=rembg-dev-cache
OUTPUTS_HOST_DIR=./outputs-dev
HOST_PORT=8501
EOF
# Instance 2: Production
cat > .env.prod << EOF
CACHE_VOLUME=trellis-prod-cache
HF_CACHE_VOLUME=huggingface-prod-cache
REMBG_CACHE_VOLUME=rembg-prod-cache
OUTPUTS_HOST_DIR=./outputs-prod
HOST_PORT=8502
EOF
# Run dev instance
docker-compose --env-file .env.dev up -d
# Run prod instance (in a different directory or with different container name)
docker-compose --env-file .env.prod -p trellis-prod up -dUse a shared cache location across multiple projects:
# Mount a centralized cache directory
cat > .env << EOF
CACHE_DIR=/shared/cache/trellis
HF_CACHE_DIR=/shared/cache/huggingface
REMBG_CACHE_DIR=/shared/cache/rembg
OUTPUTS_HOST_DIR=/shared/outputs/trellis
EOF
docker-compose build
docker-compose upPut caches on SSD for better performance:
# Use absolute paths to NVMe/SSD storage
cat > .env << EOF
OUTPUTS_HOST_DIR=/mnt/nvme/trellis-outputs
EOF
docker-compose upThe Dockerfile uses BuildKit cache mounts for faster rebuilds:
# Enable BuildKit (usually enabled by default)
export DOCKER_BUILDKIT=1
# Build with cache
./scripts/build.sh
# Subsequent builds reuse cached layers
./scripts/build.sh # Much faster!# Using build script
./scripts/build.sh --no-cache
# Using docker-compose
docker-compose build --no-cache
# Using docker
docker build --no-cache -t trellis-box .The Dockerfile uses multi-stage builds:
- Builder stage: Has all development tools and build dependencies
- Runtime stage: Only includes what's needed to run the app
This results in:
- ✅ Smaller final image (~30-40% reduction)
- ✅ Faster deployments
- ✅ Better security (fewer packages = smaller attack surface)
Layers are ordered by change frequency:
- System dependencies (rarely change)
- Poetry and Python packages (change when pyproject.toml changes)
- Application code (changes frequently)
This means editing your Python code won't trigger a full dependency reinstall.
The Trellis 3D application uses several cache directories:
- Main Cache (
CACHE_DIR): General Python/pip cache - Hugging Face Cache (
HF_CACHE_DIR): Downloaded model weights from Hugging Face - Rembg Cache (
REMBG_CACHE_DIR): U2-Net models for background removal - Outputs (
TRELLIS_OUTPUT_DIR): Generated 3D models and outputs
Docker Named Volumes (default for caches):
- Pros: Managed by Docker, persistent across container rebuilds
- Cons: Not directly accessible from host filesystem
- Use for: Model caches that don't need direct host access
Bind Mounts (default for outputs):
- Pros: Direct access from host, easy backup
- Cons: Permission issues if UID mismatches
- Use for: Output files you want to access from host
# List all volumes
docker volume ls
# Inspect a volume
docker volume inspect trellis-cache
# Remove a volume (will re-download models on next run)
docker volume rm trellis-cache
# Backup a volume
docker run --rm \
-v trellis-cache:/data \
-v $(pwd):/backup \
ubuntu tar czf /backup/trellis-cache-backup.tar.gz /data
# Restore a volume
docker run --rm \
-v trellis-cache:/data \
-v $(pwd):/backup \
ubuntu tar xzf /backup/trellis-cache-backup.tar.gz -C /To avoid downloading models on first run, you can pre-populate the cache:
# Start container and let it download models
docker-compose up
# Models are now cached in Docker volumes
# Next startup will be faster
# Alternative: Copy from another machine's cache
docker run --rm -v trellis-cache:/target -v /path/to/source:/source \
ubuntu cp -r /source/* /target/Solution: Match APP_UID to your host user ID
APP_UID=$(id -u) ./scripts/build.shError: CUDA version mismatch or driver version is insufficient
Solution: Check your NVIDIA driver version and use compatible CUDA:
nvidia-smi # Check driver version
# Use appropriate CUDA version
CUDA_VERSION=12.0.1 ./scripts/build.shSolution: Kaolin requires specific CUDA and PyTorch versions. Ensure compatibility:
- PyTorch 2.4.0 → CUDA 12.1
- Check Kaolin compatibility
Error: port is already allocated
Solution: Use a different host port
HOST_PORT=8502 docker-compose upError: Running out of disk space due to large model caches
Solution 1: Move caches to a larger disk
# In .env
CACHE_VOLUME=trellis-cache-large
# Then create volume on different disk (Docker daemon config)Solution 2: Use bind mounts to specific disk
# In .env
CACHE_DIR=/mnt/large-disk/trellis/.cache
HF_CACHE_DIR=/mnt/large-disk/trellis/huggingfaceSolution 3: Clean up unused caches
# Remove all unused volumes
docker volume prune
# Or remove specific volumes
docker-compose down
docker volume rm trellis-cache huggingface-cache rembg-cacheProblem: Models take too long to load from cache
Solution 1: Use faster storage (NVMe/SSD) for caches
# Mount cache on fast storage
cat > .env << EOF
CACHE_DIR=/mnt/nvme/.cache
HF_CACHE_DIR=/mnt/nvme/huggingface
EOFSolution 2: Increase Docker's cache size limits
Edit Docker daemon config (/etc/docker/daemon.json):
{
"data-root": "/mnt/fast-disk/docker"
}Problem: Container shows "No CUDA runtime is found" or "no CUDA-capable device is detected"
Solution 1: Verify NVIDIA Container Toolkit installation
# Check if NVIDIA Container Toolkit is installed
docker run --rm --gpus all nvidia/cuda:12.3.2-cudnn9-runtime-ubuntu22.04 nvidia-smi
# If that fails, install NVIDIA Container Toolkit
# Ubuntu/Debian:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart dockerSolution 2: Check GPU visibility on host
# Verify GPU is visible on host
nvidia-smi
# Check Docker can see GPUs
docker run --rm --gpus all ubuntu nvidia-smiSolution 3: Environment-specific GPU access
# Force specific GPU
CUDA_VISIBLE_DEVICES=0 ./scripts/run.sh
# Or in .env file
echo "CUDA_VISIBLE_DEVICES=0" >> .env
# For multiple GPUs
echo "CUDA_VISIBLE_DEVICES=0,1" >> .envIf you have custom .whl files, place them in the wheels/ directory before building:
ls wheels/
# your-custom-package.whl
./scripts/build.shNote: diff_gaussian_rasterization uses pre-built wheels for CUDA compatibility.
Note on Package Installation: The Dockerfile handles package installation with intelligent fallbacks:
- flash-attention: Tries wheel first, falls back to source build from PyPI
- diff-gaussian-rasterization: Uses local wheel if available, otherwise downloads from HuggingFace for CUDA compatibility
- nvdiffrast: Always built from source in
extensions/directory for CUDA compatibility
This ensures maximum compatibility across different CUDA versions and hardware configurations.
- Edit
pyproject.tomlto add/update dependencies - Rebuild the image:
./scripts/build.shThe build automatically runs poetry install with the updated dependencies.
- Version Pin Everything: Use specific versions for reproducible builds
- Use .env for Secrets: Never commit
.envfiles with sensitive data - Match Host UID: Set
APP_UID=$(id -u)to avoid permission issues - Tag Your Images: Use meaningful tags like
v1.0.0orprodinstead of justlatest - Test Before Deploy: Build and test locally before deploying to production
- Document Changes: If you modify defaults, document why in your project