blanchon's picture
Update
8344c24
# 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}"]