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. 【核心修复】:用最直观的方式,把看门大爷的代码写进独立的 security.js 文件里 RUN echo "const fs = require('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 = \`global.authMiddleware = (req, res, next) => { const user = process.env.SPACE_BASIC_AUTH_USERNAME || 'admin'; const pass = process.env.SPACE_BASIC_AUTH_PASSWORD || 'admin123'; 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 === user && password === pass) return next(); res.statusCode = 401; res.setHeader('WWW-Authenticate', 'Basic realm=\"Secure\"'); res.end('Unauthorized'); };\`;" >> security.js && \ echo " content = content.replace('const app =', 'const app = ; app.use(global.authMiddleware); //');" >> 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"]