Spaces:
Sleeping
Sleeping
| FROM node:20-slim | |
| ENV DEBIAN_FRONTEND=noninteractive | |
| # Build timestamp: 2026-02-03T19:55 | |
| # Note: ONNX files kept in LFS per HF policy, downloaded at startup via curl | |
| WORKDIR /app | |
| # Install curl for downloading LFS files at startup | |
| RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/* | |
| # Copy backend package.json and install ALL deps (including dev for tsx) | |
| COPY trigo-web/backend/package.json ./package.json | |
| RUN npm install | |
| # Copy backend source | |
| COPY trigo-web/backend/src/ ./backend/src/ | |
| # Copy inc folder | |
| COPY trigo-web/inc/ ./inc/ | |
| # Copy frontend dist (ONNX files will be LFS pointers, we'll download them at startup) | |
| COPY trigo-web/app/dist/ ./app/dist/ | |
| # Copy env files (only .env, .env.local is for local development only) | |
| COPY trigo-web/backend/.env ./backend/.env | |
| # Create a Docker-specific entry point that sets correct paths | |
| RUN echo 'import express from "express"; \ | |
| import { createServer } from "http"; \ | |
| import { Server } from "socket.io"; \ | |
| import cors from "cors"; \ | |
| import { GameManager } from "./backend/src/services/gameManager"; \ | |
| import { setupSocketHandlers } from "./backend/src/sockets/gameSocket"; \ | |
| const app = express(); \ | |
| const httpServer = createServer(app); \ | |
| const io = new Server(httpServer, { cors: { origin: true, methods: ["GET", "POST"], credentials: true } }); \ | |
| const gameManager = new GameManager(); \ | |
| const PORT = parseInt(process.env.PORT || "7860", 10); \ | |
| app.use(cors()); \ | |
| app.use(express.json()); \ | |
| app.use(express.static("app/dist")); \ | |
| app.get("/health", (req, res) => res.json({status: "ok", timestamp: new Date().toISOString()})); \ | |
| app.get("*", (req, res, next) => { if (req.path.startsWith("/health") || req.path.startsWith("/socket.io")) return next(); if (/\\.[a-zA-Z0-9]+$/.test(req.path)) return next(); res.sendFile("app/dist/index.html", {root: "/app"}); }); \ | |
| io.on("connection", (socket) => { console.log("Client connected:", socket.id); setupSocketHandlers(io, socket, gameManager); socket.on("disconnect", () => console.log("Client disconnected:", socket.id)); }); \ | |
| httpServer.listen(PORT, "0.0.0.0", () => console.log("Server running on port " + PORT));' > docker-entry.ts | |
| # Create startup script that downloads LFS files before starting server | |
| RUN cat <<'STARTUP' > start.sh | |
| #!/bin/bash | |
| set -e | |
| echo "=== Container startup at $(date) ===" | |
| echo "Working directory: $(pwd)" | |
| echo "Node version: $(node --version)" | |
| HF_BASE="https://huggingface.co/spaces/k-l-lambda/trigo/resolve/main/trigo-web/app/dist" | |
| # List of ONNX files to download (relative to app/dist) | |
| ONNX_FILES=( | |
| "onnx/20251230-trigo-value-llama-l6-h64-it2_251221-value0.01-pretrain/LlamaCausalLM_ep0036_evaluation.onnx" | |
| "onnx/20251230-trigo-value-llama-l6-h64-it2_251221-value0.01-pretrain/LlamaCausalLM_ep0036_tree.onnx" | |
| ) | |
| echo "Downloading ONNX model files..." | |
| for file in "${ONNX_FILES[@]}"; do | |
| dir=$(dirname "app/dist/$file") | |
| mkdir -p "$dir" | |
| echo " Downloading $file..." | |
| if curl -fsSL "$HF_BASE/$file" -o "app/dist/$file"; then | |
| size=$(stat -c%s "app/dist/$file" 2>/dev/null || echo "unknown") | |
| echo " Downloaded: $size bytes" | |
| else | |
| echo " WARNING: Failed to download $file" | |
| fi | |
| done | |
| echo "=== Checking downloaded files ===" | |
| ls -la app/dist/onnx/20251230-trigo-value-llama-l6-h64-it2_251221-value0.01-pretrain/ 2>/dev/null || echo "ONNX directory not found" | |
| echo "=== Starting server ===" | |
| exec npx tsx docker-entry.ts | |
| STARTUP | |
| RUN chmod +x start.sh | |
| ENV PORT=7860 | |
| ENV HOST=0.0.0.0 | |
| ENV NODE_ENV=production | |
| EXPOSE 7860 | |
| CMD ["./start.sh"] | |