diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1fc6d6c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +node_modules +dist +.vscode +.claude +.idea +.git +.gitignore +*.log +http.log +npm-debug.log +.DS_Store + +# 构建中间产物和测试文件 +deploy.sh +cursor2api_deployment.zip +test*.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3cfedaa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +# ==== Stage 1: 构建阶段 (Builder) ==== +FROM node:22-alpine AS builder + +# 设置工作目录 +WORKDIR /app + +# 仅拷贝包配置并安装所有依赖项(利用 Docker 缓存层) +COPY package.json package-lock.json ./ +RUN npm ci + +# 拷贝项目源代码并执行 TypeScript 编译 +COPY tsconfig.json ./ +COPY src ./src +COPY jscode ./jscode +RUN npm run build + +# ==== Stage 2: 生产运行阶段 (Runner) ==== +FROM node:22-alpine AS runner + +WORKDIR /app + +# 设置为生产环境 +ENV NODE_ENV=production + +# 出于安全考虑,避免使用 root 用户运行服务 +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 cursor + +# 拷贝包配置并仅安装生产环境依赖(极大减小镜像体积) +COPY package.json package-lock.json ./ +RUN npm ci --omit=dev \ + && npm cache clean --force + +# 从 builder 阶段拷贝编译后的产物 +COPY --from=builder --chown=cursor:nodejs /app/dist ./dist +# 拷贝必要的运行时资源目录 +COPY --from=builder --chown=cursor:nodejs /app/jscode ./jscode + +# 明确并赋予权限,因为在脚本验证里我们需要写入 /tmp +# 默认情况下 Alpine 的 /tmp 对所有用户都可写,这步安全地确保用户权限 +USER cursor + +# 声明对外暴露的端口 +EXPOSE 3010 + +# 启动服务 +CMD ["npm", "start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2d91bea --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +services: + cursor2api: + build: + context: . + dockerfile: Dockerfile + image: cursor2api:latest + container_name: cursor2api + restart: unless-stopped + ports: + - "3010:3010" + # volumes: + # 如果你有外部的 config.yaml 文件,可以取消下面这行的注释来挂载配置文件 + # - ./config.yaml:/app/config.yaml:ro + environment: + - NODE_ENV=production + - PORT=3010 + - TIMEOUT=120 + # ⚠️ 部署到海外机器无需代理,如果在国内云,取消注释并填入你的本机 http/socks 代理 + # - PROXY=http://host.docker.internal:7890 + + # [可选环境变量] 以下变量如果你在此声明,将会覆盖 config.yaml 的配置逻辑: + # - CURSOR_MODEL=anthropic/claude-sonnet-4.6 + # - SCRIPT_URL=https://... + # - FP=ey...