3v324v23 commited on
Commit
a0333cd
·
1 Parent(s): 0dd2082

Optimize for Hugging Face deployment

Browse files

Multi-stage Docker build, static serving, and single-origin API config

server/Dockerfile → Dockerfile RENAMED
@@ -1,7 +1,16 @@
1
- # Use Node.js 20 base image
 
 
 
 
 
 
 
 
2
  FROM node:20
 
3
 
4
- # Install Google Chrome stable and its dependencies for Puppeteer
5
  RUN apt-get update && apt-get install -y \
6
  wget \
7
  gnupg \
@@ -10,40 +19,32 @@ RUN apt-get update && apt-get install -y \
10
  && apt-get update \
11
  && apt-get install -y \
12
  google-chrome-stable \
13
- fonts-ipafont-gothic \
14
- fonts-wqy-zenhei \
15
- fonts-thai-tlwg \
16
- fonts-kacst \
17
  fonts-freefont-ttf \
18
- libxss1 \
19
  --no-install-recommends \
20
  && rm -rf /var/lib/apt/lists/*
21
 
22
- # Create app directory
23
- WORKDIR /app
24
-
25
- # Copy package files
26
- COPY package*.json ./
27
-
28
- # Install dependencies (ensure puppeteer downloads its own chrome if needed, or uses system)
29
  RUN npm install
 
30
 
31
- # Copy app source
32
- COPY . .
 
 
33
 
34
- # Hugging Face Spaces default port
35
  ENV PORT=7860
36
- EXPOSE 7860
37
-
38
- # Puppeteer environment variables
39
- # Tell Puppeteer to use the installed Google Chrome
40
  ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
41
  ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
42
 
43
- # Hugging Face requires a non-root user (id 1000)
 
 
44
  RUN useradd -m -u 1000 user
45
- RUN chown -R user:user /app
46
  USER user
47
 
48
- # Command to run the application
49
  CMD ["node", "src/index.js"]
 
1
+ # Stage 1: Build the Client
2
+ FROM node:20 AS client-builder
3
+ WORKDIR /client
4
+ COPY client/package*.json ./
5
+ RUN npm install
6
+ COPY client/ .
7
+ RUN npm run build
8
+
9
+ # Stage 2: Final Production Environment
10
  FROM node:20
11
+ WORKDIR /app
12
 
13
+ # Install Google Chrome for Puppeteer inside Docker
14
  RUN apt-get update && apt-get install -y \
15
  wget \
16
  gnupg \
 
19
  && apt-get update \
20
  && apt-get install -y \
21
  google-chrome-stable \
 
 
 
 
22
  fonts-freefont-ttf \
 
23
  --no-install-recommends \
24
  && rm -rf /var/lib/apt/lists/*
25
 
26
+ # Copy Server files
27
+ COPY server/package*.json ./
 
 
 
 
 
28
  RUN npm install
29
+ COPY server/ .
30
 
31
+ # Copy Client build (the server expects it at ../client/dist relative to server/src/index.js)
32
+ # In this single container setup at /app, it will be at /app/../client/dist ??
33
+ # Let's adjust server's clientPath logic slightly or copy it to /client/dist
34
+ COPY --from=client-builder /client/dist /client/dist
35
 
36
+ # Environment
37
  ENV PORT=7860
38
+ ENV NODE_ENV=production
 
 
 
39
  ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
40
  ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
41
 
42
+ EXPOSE 7860
43
+
44
+ # Hugging Face Spaces non-root user (id 1000)
45
  RUN useradd -m -u 1000 user
46
+ RUN chown -R user:user /app /client
47
  USER user
48
 
49
+ # Run the server
50
  CMD ["node", "src/index.js"]
client/src/api/client.js CHANGED
@@ -1,4 +1,6 @@
1
- const BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api';
 
 
2
 
3
  async function request(endpoint, options = {}) {
4
  const url = `${BASE_URL}${endpoint}`;
 
1
+ const BASE_URL = typeof window !== 'undefined' && window.location.hostname === 'localhost'
2
+ ? 'http://localhost:3001/api'
3
+ : '/api';
4
 
5
  async function request(endpoint, options = {}) {
6
  const url = `${BASE_URL}${endpoint}`;
server/src/index.js CHANGED
@@ -37,12 +37,24 @@ app.get('/', (req, res) => {
37
  });
38
  });
39
 
 
 
40
  // Routes
41
  app.use('/api/search', searchRoutes);
42
  app.use(rateLimiter);
43
 
44
  app.use('/api', routes);
45
 
 
 
 
 
 
 
 
 
 
 
46
  app.use((req, res) => {
47
  res.status(404).json({ success: false, error: 'Route not found' });
48
  });
 
37
  });
38
  });
39
 
40
+ const path = require('path');
41
+
42
  // Routes
43
  app.use('/api/search', searchRoutes);
44
  app.use(rateLimiter);
45
 
46
  app.use('/api', routes);
47
 
48
+ // Serve Static Files for Deployment
49
+ const clientPath = path.join(__dirname, '../../client/dist');
50
+ app.use(express.static(clientPath));
51
+
52
+ // Handle React SPA routing
53
+ app.get('*', (req, res, next) => {
54
+ if (req.path.startsWith('/api')) return next();
55
+ res.sendFile(path.join(clientPath, 'index.html'));
56
+ });
57
+
58
  app.use((req, res) => {
59
  res.status(404).json({ success: false, error: 'Route not found' });
60
  });