lydgs commited on
Commit
54e065a
·
verified ·
1 Parent(s): a944561

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +44 -33
Dockerfile CHANGED
@@ -1,8 +1,22 @@
1
  FROM node:20-slim AS builder
2
  WORKDIR /app
3
- RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
 
 
 
 
 
 
 
 
 
4
  RUN git clone https://github.com/tashfeenahmed/freellmapi.git .
5
- RUN npm install
 
 
 
 
 
6
  RUN npm run build
7
 
8
  # --- 生产运行环境 ---
@@ -10,41 +24,38 @@ FROM node:20-slim AS runner
10
  WORKDIR /app
11
 
12
  COPY --from=builder /app ./
 
 
13
  RUN mkdir -p /data/freellm
14
 
15
- # 1. 前端静态路由修复
16
  RUN cp -r client/dist/* server/dist/public/ 2>/dev/null || cp -r client/dist/* server/public/ 2>/dev/null || true
17
 
18
- # 2. 注入基础配
19
  EXPOSE 7860
20
  ENV PORT=7860
21
- ENV NODE_ENV=production
22
- ENV DATABASE_URL="file:/data/database.sqlite"
23
-
24
- # 3. 【无损看门狗】直接把拦截逻辑写进一个独立中间件,然后利用 Node.js 极低层的 http 模块拦截器
25
- # 无论项目底层怎么写、变量叫什么名字,只要请求进来,首先必过此关,绝不引发任何语法冲突!
26
- RUN echo "import fs from 'fs';" > security.js && \
27
- echo "const file = 'server/dist/index.js';" >> security.js && \
28
- echo "if (fs.existsSync(file)) {" >> security.js && \
29
- echo " let content = fs.readFileSync(file, 'utf8');" >> security.js && \
30
- echo " const injectCode = \` \
31
- import http from 'http'; \
32
- const originalCreateServer = http.createServer; \
33
- http.createServer = function(onion) { \
34
- return originalCreateServer.call(this, (req, res) => { \
35
- const user = process.env.SPACE_BASIC_AUTH_USERNAME || 'admin'; \
36
- const pass = process.env.SPACE_BASIC_AUTH_PASSWORD || 'admin123'; \
37
- if (req.url.startsWith('/v1')) return onion(req, res); \
38
- const b64auth = (req.headers.authorization || '').split(' ')[1] || ''; \
39
- const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':'); \
40
- if (login === user && password === pass) return onion(req, res); \
41
- res.statusCode = 401; \
42
- res.setHeader('WWW-Authenticate', 'Basic realm=\"Secure\"'); \
43
- res.end('Unauthorized'); \
44
- }); \
45
- }; \n\`;" >> security.js && \
46
- echo " fs.writeFileSync(file, injectCode + content, 'utf8');" >> security.js && \
47
- echo "}" >> security.js
48
-
49
- # 4. 完美运行命令
50
  CMD ["sh", "-c", "rm -rf /app/server/data && ln -s /data/freellm /app/server/data && node security.js && export ENCRYPTION_KEY=$(node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\") && node server/dist/index.js"]
 
1
  FROM node:20-slim AS builder
2
  WORKDIR /app
3
+
4
+ # 安装编译 better-sqlite3 所需的工具
5
+ RUN apt-get update && apt-get install -y \
6
+ git \
7
+ python3 \
8
+ make \
9
+ g++ \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # 克隆 FreeLLMAPI 仓库(使用 GitHub 镜像加速,可选)
13
  RUN git clone https://github.com/tashfeenahmed/freellmapi.git .
14
+
15
+ # 安装依赖(使用国内 npm 镜像加速,可选)
16
+ RUN npm config set registry https://registry.npmmirror.com && \
17
+ npm install
18
+
19
+ # 构建项目(生成 dist 目录)
20
  RUN npm run build
21
 
22
  # --- 生产运行环境 ---
 
24
  WORKDIR /app
25
 
26
  COPY --from=builder /app ./
27
+
28
+ # 创建数据目录
29
  RUN mkdir -p /data/freellm
30
 
31
+ # 前端静态文件适配(如果存在)
32
  RUN cp -r client/dist/* server/dist/public/ 2>/dev/null || cp -r client/dist/* server/public/ 2>/dev/null || true
33
 
34
+ # 运行端口(Hugging Face 要求 7860)
35
  EXPOSE 7860
36
  ENV PORT=7860
37
+ NODE_ENV=production
38
+ DATABASE_URL="file:/data/database.sqlite"
39
+
40
+ # 可选添加简单Basic Auth 保护(防止你的网关被公开滥用)
41
+ # 你可以在 Hugging Face Space 的 Settings -> Repository secrets 中设置 SPACE_BASIC_AUTH_USERNAME 和 SPACE_BASIC_AUTH_PASSWORD
42
+ RUN echo "import http from 'http';" > security.js && \
43
+ echo "const originalCreateServer = http.createServer;" >> security.js && \
44
+ echo "http.createServer = function(onRequest) {" >> security.js && \
45
+ echo " return originalCreateServer.call(this, (req, res) => {" >> security.js && \
46
+ echo " const auth = req.headers.authorization || '';" >> security.js && \
47
+ echo " const b64auth = auth.split(' ')[1] || '';" >> security.js && \
48
+ echo " const [user, pwd] = Buffer.from(b64auth, 'base64').toString().split(':');" >> security.js && \
49
+ echo " const validUser = process.env.SPACE_BASIC_AUTH_USERNAME || 'admin';" >> security.js && \
50
+ echo " const validPwd = process.env.SPACE_BASIC_AUTH_PASSWORD || 'admin123';" >> security.js && \
51
+ echo " if (req.url.startsWith('/v1') || (user === validUser && pwd === validPwd)) {" >> security.js && \
52
+ echo " return onRequest(req, res);" >> security.js && \
53
+ echo " }" >> security.js && \
54
+ echo " res.statusCode = 401;" >> security.js && \
55
+ echo " res.setHeader('WWW-Authenticate', 'Basic realm=\"FreeLLMAPI\"');" >> security.js && \
56
+ echo " res.end('Unauthorized');" >> security.js && \
57
+ echo " });" >> security.js && \
58
+ echo "};" >> security.js
59
+
60
+ # 启动命令:链接数据目录、注入安全中间件、设置 ENCRYPTION_KEY、启动服务
 
 
 
 
 
61
  CMD ["sh", "-c", "rm -rf /app/server/data && ln -s /data/freellm /app/server/data && node security.js && export ENCRYPTION_KEY=$(node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\") && node server/dist/index.js"]