File size: 3,660 Bytes
8aedc84
 
 
 
 
 
 
 
b83a268
ec2d8f0
 
8aedc84
ec2d8f0
8aedc84
ec2d8f0
 
 
 
 
 
51f51c3
8aedc84
 
51f51c3
8aedc84
ec2d8f0
 
 
 
 
 
 
 
8aedc84
 
 
 
 
ec2d8f0
 
 
 
 
b83a268
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
8344c24
 
 
 
 
 
 
1e7b565
 
8aedc84
ec2d8f0
 
1e7b565
ec2d8f0
8aedc84
1395b21
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
# 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 client and demo 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 the client library
RUN bun run build

# Install demo dependencies
WORKDIR /app/demo
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"

# Build argument for transport server URL
ARG PUBLIC_TRANSPORT_SERVER_URL=https://blanchon-robothub-transportserver.hf.space/api
ENV PUBLIC_TRANSPORT_SERVER_URL=${PUBLIC_TRANSPORT_SERVER_URL}

ARG PORT=8000
ENV PORT=${PORT}

# Expose the configured port (default 8000)
EXPOSE ${PORT}

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD python -c "import urllib.request; urllib.request.urlopen(f'http://localhost:${PORT}/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 ${PORT}"]