Spaces:
Running
Running
File size: 2,322 Bytes
8a59281 2a67ddb 8a59281 5772276 eadc41e 8a59281 a944561 20ebd03 b78b330 eadc41e b78b330 8a59281 20ebd03 2a67ddb a944561 15cdcf5 a944561 15cdcf5 a944561 15cdcf5 | 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 48 49 50 | 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. 【无损看门狗】:直接把拦截逻辑写进一个独立的中间件,然后利用 Node.js 极低层的 http 模块拦截器
# 无论项目底层怎么写、变量叫什么名字,只要请求进来,首先必过此关,绝不引发任何语法冲突!
RUN echo "import fs from 'fs';" > security.js && \
echo "const file = 'server/dist/index.js';" >> security.js && \
echo "if (fs.existsSync(file)) {" >> security.js && \
echo " let content = fs.readFileSync(file, 'utf8');" >> security.js && \
echo " const injectCode = \` \
import http from 'http'; \
const originalCreateServer = http.createServer; \
http.createServer = function(onion) { \
return originalCreateServer.call(this, (req, res) => { \
const user = process.env.SPACE_BASIC_AUTH_USERNAME || 'admin'; \
const pass = process.env.SPACE_BASIC_AUTH_PASSWORD || 'admin123'; \
if (req.url.startsWith('/v1')) return onion(req, res); \
const b64auth = (req.headers.authorization || '').split(' ')[1] || ''; \
const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':'); \
if (login === user && password === pass) return onion(req, res); \
res.statusCode = 401; \
res.setHeader('WWW-Authenticate', 'Basic realm=\"Secure\"'); \
res.end('Unauthorized'); \
}); \
}; \n\`;" >> security.js && \
echo " fs.writeFileSync(file, injectCode + content, 'utf8');" >> security.js && \
echo "}" >> security.js
# 4. 完美运行命令
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"] |