File size: 3,565 Bytes
8aedc84
 
 
 
 
 
 
 
 
ec2d8f0
 
 
8aedc84
ec2d8f0
8aedc84
ec2d8f0
 
 
 
 
 
 
8aedc84
 
 
ec2d8f0
8aedc84
ec2d8f0
 
 
 
 
 
 
 
 
8aedc84
 
 
 
 
ec2d8f0
 
 
 
 
 
 
8aedc84
 
ec2d8f0
 
 
 
 
8aedc84
 
 
 
 
 
ec2d8f0
 
 
 
 
 
 
8aedc84
ec2d8f0
 
 
 
 
 
8aedc84
 
ec2d8f0
 
8aedc84
ec2d8f0
 
 
8aedc84
ec2d8f0
 
8aedc84
ec2d8f0
 
8aedc84
 
ec2d8f0
 
 
8aedc84
 
ec2d8f0
8aedc84
ec2d8f0
 
 
8aedc84
 
ec2d8f0
8aedc84
 
ec2d8f0
 
 
 
8aedc84
ec2d8f0
8aedc84
 
ec2d8f0
 
 
 
8aedc84
ec2d8f0
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
# Multi-stage Dockerfile for LeRobot Arena Transport Server
# Stage 1: Build frontend with Bun (client library + demo)
FROM oven/bun:1-alpine AS frontend-builder

WORKDIR /app

# Install git for dependencies that might need it
RUN apk add --no-cache git

# Copy package files for better caching
COPY client/js/package.json client/js/tsconfig.json* ./client/js/
COPY demo/package.json demo/tsconfig.json* demo/svelte.config.js* ./demo/

# Install client library dependencies first
WORKDIR /app/client/js
RUN bun install --frozen-lockfile

# Copy client library source code
COPY client/js/src/ ./src/
COPY client/js/bun.lock* ./

# Build and link client library
RUN bun run build
RUN bun link

# Install demo dependencies with linked client library
WORKDIR /app/demo
RUN bun link @robothub/transport-server-client
RUN bun install --frozen-lockfile

# Copy demo source code
COPY demo/src/ ./src/
COPY demo/static/ ./static/
COPY demo/vite.config.ts* demo/tailwind.config.* demo/.prettierrc* ./

# Build demo application
RUN bun run build

# Stage 2: Python backend with uv
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim

# Set environment variables for Python and UV
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    UV_SYSTEM_PYTHON=1 \
    UV_COMPILE_BYTECODE=1 \
    UV_CACHE_DIR=/tmp/uv-cache

# Install system dependencies needed for video processing
RUN apt-get update && apt-get install -y \
    # Build tools for compiling Python packages
    build-essential \
    gcc \
    g++ \
    # Video processing libraries
    libavformat-dev \
    libavcodec-dev \
    libavdevice-dev \
    libavutil-dev \
    libswscale-dev \
    libswresample-dev \
    # Additional system libraries
    libgl1-mesa-glx \
    libglib2.0-0 \
    libsm6 \
    libxext6 \
    libxrender-dev \
    libgomp1 \
    pkg-config \
    # FFmpeg for video processing
    ffmpeg \
    # Git for potential model downloads
    git \
    # Clean up
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Create a non-root user (required for HF Spaces)
RUN groupadd -r appuser && useradd -r -g appuser -m -s /bin/bash -u 1000 appuser

# Set working directory and ensure it's owned by appuser
WORKDIR /app
RUN chown -R appuser:appuser /app

# Switch to appuser before installing dependencies
USER appuser

# Copy dependency files for better layer caching
COPY --chown=appuser:appuser server/pyproject.toml server/uv.lock* ./server/

# Install dependencies first (better caching)
WORKDIR /app/server
RUN --mount=type=cache,target=/tmp/uv-cache,uid=1000,gid=1000 \
    uv sync --locked --no-install-project --no-dev

# Copy the rest of the Python backend
COPY --chown=appuser:appuser server/ ./

# Install the project in non-editable mode for production
RUN --mount=type=cache,target=/tmp/uv-cache,uid=1000,gid=1000 \
    uv sync --locked --no-editable --no-dev

# Copy built frontend from previous stage with proper ownership
COPY --chown=appuser:appuser --from=frontend-builder /app/demo/build /app/static-frontend

# Set working directory back to app root
WORKDIR /app

# Add virtual environment to PATH
ENV PATH="/app/server/.venv/bin:$PATH"

# Expose port 7860 (HuggingFace Spaces default)
EXPOSE 7860

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/health')" || exit 1

# Start the FastAPI server (serves both frontend and backend)
CMD ["sh", "-c", "cd server && SERVE_FRONTEND=true uv run python launch_with_ui.py --host 0.0.0.0 --port 7860"]