liminal-sessions / Dockerfile
Severian's picture
Update Dockerfile
503e9a7 verified
# Simple Dockerfile for Hugging Face Spaces
# No nginx needed - just serve static files with Python
# Stage 1: Build the application
FROM node:18-alpine AS builder
WORKDIR /app
# Install build dependencies
RUN apk add --no-cache python3 make g++
# Copy package files
COPY package*.json ./
COPY tsconfig*.json ./
COPY vite.config.ts ./
# Install dependencies
RUN npm install
# Copy source code
COPY src/ ./src/
COPY public/ ./public/
COPY index.html ./
# Build the application
ENV NODE_ENV=production
RUN npm run build
# Verify build output
RUN ls -la dist/ && echo "βœ… Build completed successfully"
# Stage 2: Simple Python server for static files
FROM python:3.11-slim
WORKDIR /app
# Copy built app from builder stage
COPY --from=builder /app/dist ./
# Create a simple server script
RUN echo '#!/usr/bin/env python3\n\
import http.server\n\
import socketserver\n\
import os\n\
import urllib.parse\n\
from pathlib import Path\n\
\n\
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):\n\
def end_headers(self):\n\
self.send_my_headers()\n\
super().end_headers()\n\
\n\
def send_my_headers(self):\n\
self.send_header("Access-Control-Allow-Origin", "*")\n\
self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")\n\
self.send_header("Access-Control-Allow-Headers", "*")\n\
\n\
def do_GET(self):\n\
# Parse URL to get clean path without query parameters\n\
parsed_url = urllib.parse.urlparse(self.path)\n\
clean_path = parsed_url.path\n\
\n\
# Handle SPA routing - serve index.html for non-file requests\n\
if clean_path != "/" and clean_path != "" and "." not in clean_path:\n\
# Check if this looks like a file path\n\
try:\n\
if clean_path.startswith("/"):\n\
file_path = clean_path[1:]\n\
else:\n\
file_path = clean_path\n\
\n\
# Only check if path is reasonable length and format\n\
if len(file_path) < 200 and not file_path.startswith("?"):\n\
if not Path(file_path).exists():\n\
self.path = "/index.html"\n\
else:\n\
# Very long path or starts with ?, serve index.html\n\
self.path = "/index.html"\n\
except (OSError, ValueError):\n\
# Any error in path checking, serve index.html\n\
self.path = "/index.html"\n\
else:\n\
# Keep original path for actual files\n\
self.path = clean_path\n\
\n\
return super().do_GET()\n\
\n\
def guess_type(self, path):\n\
# Add audio MIME types\n\
if path.endswith(".mp3"):\n\
return "audio/mpeg"\n\
elif path.endswith(".wav"):\n\
return "audio/wav"\n\
elif path.endswith(".ogg"):\n\
return "audio/ogg"\n\
else:\n\
return super().guess_type(path)\n\
\n\
PORT = int(os.environ.get("PORT", 7860))\n\
files = os.listdir(".")\n\
print(f"πŸš€ Starting server on port {PORT}")\n\
print(f"πŸ“ Serving files from: {os.getcwd()}")\n\
print(f"πŸ“‹ Files available: {files}")\n\
\n\
with socketserver.TCPServer(("", PORT), MyHTTPRequestHandler) as httpd:\n\
print(f"βœ… Server running at http://0.0.0.0:{PORT}")\n\
httpd.serve_forever()\n\
' > server.py && chmod +x server.py
# Expose port 7860 (HF Spaces default)
EXPOSE 7860
# Start the server
CMD ["python3", "server.py"]