File size: 4,915 Bytes
a709708
 
 
 
 
 
1c36423
a709708
 
d91502d
1c36423
bdd1d56
a709708
 
 
 
 
 
d91502d
1c36423
 
a709708
 
 
 
 
 
6d80c97
 
 
a709708
 
 
6d80c97
a709708
 
6d80c97
 
 
 
 
 
 
 
 
a709708
6d80c97
a709708
c6733ce
a709708
6d80c97
 
 
c6733ce
 
 
 
 
 
 
 
 
 
 
 
6d80c97
a709708
 
594aee7
 
 
 
 
 
a709708
 
 
 
 
2e3f535
 
 
1c36423
 
 
a709708
 
 
 
 
 
5a8a0c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a709708
 
 
 
a7b14bb
 
b434289
1c36423
 
 
594aee7
1c36423
594aee7
1c36423
 
 
 
a709708
 
 
1c36423
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
FROM python:3.10-slim

# 创建用户(HF Spaces 要求 UID=1000)
RUN useradd -m -u 1000 user
USER root

# 安装系统依赖(Blender + 完整的无头渲染支持)
RUN apt-get update && apt-get install -y \
    blender \
    xvfb \
    xorg \
    libgl1 \
    libglib2.0-0 \
    libsm6 \
    libxrender1 \
    libxext6 \
    libxi6 \
    libxkbcommon-x11-0 \
    libgomp1 \
    libxxf86vm1 \
    libxfixes3 \
    wget \
    unzip \
    git \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# 下载完整 LDraw 库(官方 + 非官方零件)
RUN echo "📦 Downloading complete LDraw library..." && \
    # 官方零件库 (~18MB → ~70MB)
    wget -q --retry-connrefused --waitretry=5 --tries=3 \
        https://library.ldraw.org/library/updates/complete.zip \
        -O /tmp/ldraw.zip && \
    echo "📂 Extracting official LDraw library..." && \
    unzip -q /tmp/ldraw.zip -d /home/user/ && \
    rm /tmp/ldraw.zip && \
    # 非官方零件库 (~12MB → ~50MB)
    echo "📦 Downloading unofficial LDraw parts..." && \
    wget -q --retry-connrefused --waitretry=5 --tries=3 \
        https://library.ldraw.org/library/unofficial/ldrawunf.zip \
        -O /tmp/ldrawunf.zip && \
    mkdir -p /home/user/ldraw/unofficial && \
    echo "📂 Extracting unofficial parts..." && \
    unzip -q /tmp/ldrawunf.zip -d /home/user/ldraw/unofficial/ && \
    rm /tmp/ldrawunf.zip && \
    chown -R user:user /home/user/ldraw && \
    echo "✅ Complete LDraw library installed"

# 验证 LDraw 库完整性(增强版 - 详细输出)
RUN test -d /home/user/ldraw/parts && \
    test -d /home/user/ldraw/unofficial/parts && \
    echo "📊 Official parts: $(find /home/user/ldraw/parts -name '*.dat' | wc -l)" && \
    echo "📊 Unofficial parts: $(find /home/user/ldraw/unofficial/parts -name '*.dat' | wc -l)" && \
    echo "📦 Sample official parts:" && \
    ls /home/user/ldraw/parts/*.dat 2>/dev/null | head -10 | xargs -n 1 basename && \
    echo "📦 Sample unofficial parts:" && \
    ls /home/user/ldraw/unofficial/parts/*.dat 2>/dev/null | head -10 | xargs -n 1 basename && \
    echo "🔍 Checking critical parts from GPT outputs..." && \
    for part in 4081.dat 60470.dat 2431.dat 92583.dat 92593.dat 18892.dat 15068.dat 2412.dat 61678.dat 3666.dat; do \
        if find /home/user/ldraw -name "$part" | grep -q .; then \
            echo "  ✓ Found $part"; \
        else \
            echo "  ✗ Missing $part (will check if it's a subpart)"; \
        fi; \
    done && \
    echo "✓ LDraw installation verified" || \
    (echo "✗ LDraw installation failed" && exit 1)

# 以 root 身份预创建 X11 socket 目录(解决 Xvfb 权限问题)
RUN mkdir -p /tmp/.X11-unix && \
    chmod 1777 /tmp/.X11-unix && \
    chown root:root /tmp/.X11-unix && \
    echo "✓ X11 socket directory created"

# 切换到普通用户
USER user
ENV HOME=/home/user \
    PATH=/home/user/.local/bin:$PATH \
    LDRAW_LIBRARY_PATH=/home/user/ldraw \
    HF_HOME=/home/user/.cache/huggingface \
    HF_HUB_CACHE=/home/user/.cache/huggingface/hub \
    TRANSFORMERS_CACHE=/home/user/.cache/huggingface/transformers \
    HF_HUB_DISABLE_XET=1 \
    DISPLAY=:99 \
    LIBGL_ALWAYS_SOFTWARE=1

WORKDIR $HOME/app

# 复制项目文件
COPY --chown=user . $HOME/app

# 验证 ImportLDraw 插件,若不存在则下载
RUN if [ ! -d "$HOME/app/code/ImportLDraw" ] || [ ! -f "$HOME/app/code/ImportLDraw/__init__.py" ]; then \
    echo "⚠️  ImportLDraw not found in repo, downloading..."; \
    wget -q https://github.com/TobyLobster/ImportLDraw/archive/refs/tags/v1.2.1.zip -O /tmp/importldraw.zip && \
    unzip -q /tmp/importldraw.zip -d /tmp/ && \
    mv /tmp/ImportLDraw-1.2.1 $HOME/app/code/ImportLDraw && \
    rm /tmp/importldraw.zip && \
    echo "✅ ImportLDraw downloaded successfully"; \
else \
    echo "✅ ImportLDraw found in repo"; \
fi

# 验证插件已正确部署
RUN ls -la $HOME/app/code/ImportLDraw/__init__.py || \
    (echo "❌ ImportLDraw deployment failed" && exit 1)

# 安装 Python 依赖
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt

# 注意:模型通过 README.md 的 preload_from_hub 自动下载(HF Spaces 官方推荐方式)
# 下载到 ~/.cache/huggingface/hub/ 并在运行时通过 HF_HUB_CACHE 环境变量访问

# 创建启动脚本(先启动 Xvfb,再运行应用)
RUN echo '#!/bin/bash\n\
echo "🖥️  启动虚拟显示服务器 Xvfb..."\n\
Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +extension RENDER +render -noreset -nolisten tcp -nolisten unix &\n\
sleep 2\n\
echo "✅ Xvfb 已启动 (DISPLAY=:99, 无 Unix socket)"\n\
echo "🚀 启动应用..."\n\
exec python code/demo.py' > /home/user/start.sh && \
    chmod +x /home/user/start.sh

# 暴露端口(Gradio 默认)
EXPOSE 7860

# 启动命令(使用启动脚本)
CMD ["/home/user/start.sh"]