File size: 1,966 Bytes
8a59281
 
 
 
 
 
 
2a67ddb
8a59281
 
 
5772276
eadc41e
8a59281
b78b330
20ebd03
 
b78b330
eadc41e
b78b330
8a59281
20ebd03
2a67ddb
b78b330
5772276
b78b330
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
FROM node:20-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
RUN git clone https://github.com/tashfeenahmed/freellmapi.git .
RUN npm install
RUN npm run build

# --- 生产运行环境 ---
FROM node:20-slim AS runner
WORKDIR /app

COPY --from=builder /app ./
RUN mkdir -p /data/freellm

# 1. 前端路由修复
RUN cp -r client/dist/* server/dist/public/ 2>/dev/null || cp -r client/dist/* server/public/ 2>/dev/null || true

# 2. 注入基础配置
EXPOSE 7860
ENV PORT=7860
ENV NODE_ENV=production
ENV DATABASE_URL="file:/data/database.sqlite"

# 3. 【原生绝杀】:在容器启动前,动态往核心代码里塞入一段 Basic Auth 拦截逻辑
CMD ["sh", "-c", "rm -rf /app/server/data && ln -s /data/freellm /app/server/data && \
    # 动态把密码拦截代码注入到后端的入口文件中 \
    node -e \" \
    const fs = require('fs'); \
    const file = 'server/dist/index.js'; \
    if (fs.existsSync(file)) { \
      let content = fs.readFileSync(file, 'utf8'); \
      const injectCode = ` \
        // 密码锁中间件 \
        global.authMiddleware = (req, res, next) => { \
          const user = process.env.SPACE_BASIC_AUTH_USERNAME || 'admin'; \
          const pass = process.env.SPACE_BASIC_AUTH_PASSWORD || 'admin123'; \
          const auth = { login: user, password: pass }; \
          const b64auth = (req.headers.authorization || '').split(' ')[1] || ''; \
          const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':'); \
          if (req.url.startsWith('/v1')) return next(); \
          if (login && password && login === auth.login && password === auth.password) return next(); \
          res.statusCode = 401; \
          res.setHeader('WWW-Authenticate', 'Basic realm=\\\"Secure Area\\\"'); \
          res.end('Unauthorized'); \
        }; \
      `; \
      content = injectCode + content.replace('const app =', 'const app = ; app