Skip to content

自托管部署

概述

自托管部署允许你在自有服务器上运行 Fullstack Pack,提供更多控制和灵活性。

架构说明

自托管部署

  • 后端: Node.js 服务器(使用 @hono/node-server
  • 前端: 任何静态文件服务器(Nginx、Apache、Node.js 等)
  • 数据库: PostgreSQL(直接 TCP 连接)

部署步骤

1. 后端部署

1.1 环境要求

  • Node.js >= 18.0.0
  • PostgreSQL 数据库
  • pnpm >= 8.0.0

1.2 安装依赖

bash
cd apps/server
pnpm install

1.3 配置环境变量

创建 .env 文件:

bash
# 必需
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
JWT_SECRET=your-secret-key-at-least-32-characters-long

# 可选
NODE_ENV=production
SERVER_PORT=3000
SERVER_HOST=0.0.0.0
JWT_EXPIRES_IN=7d
CORS_ORIGIN=https://your-frontend-domain.com

1.4 数据库迁移

bash
# 生成 Prisma Client
pnpm db:generate

# 推送数据库 schema(开发环境)
pnpm db:push

# 或使用 migrations(生产环境推荐)
npx prisma migrate deploy

1.5 构建和启动

bash
# 构建
pnpm build

# 启动(使用 Node.js)
pnpm start

# 或使用 PM2(推荐生产环境)
pm2 start dist/server.js --name fullstackpack-api

1.6 使用 Docker(可选)

创建 Dockerfile

dockerfile
FROM node:20-alpine

WORKDIR /app

# 安装 pnpm
RUN npm install -g pnpm

# 复制依赖文件
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/server/package.json ./apps/server/
COPY packages/*/package.json ./packages/*/

# 安装依赖
RUN pnpm install --frozen-lockfile

# 复制源代码
COPY . .

# 构建
RUN pnpm --filter server build

WORKDIR /app/apps/server

# 暴露端口
EXPOSE 3000

# 启动
CMD ["node", "dist/server.js"]

构建和运行:

bash
docker build -t fullstackpack-api .
docker run -p 3000:3000 --env-file .env fullstackpack-api

2. 前端部署

2.1 构建前端应用

Web 应用

bash
cd apps/web
pnpm install
pnpm build
# 构建产物在 dist/ 目录

认证门户

bash
cd apps/auth-portal
pnpm install
pnpm build
# 构建产物在 dist/ 目录

2.2 配置环境变量

在构建前设置环境变量:

bash
# Web 应用
export VITE_API_URL=https://api.yourdomain.com
export VITE_AUTH_PORTAL_URL=https://auth.yourdomain.com

# 认证门户
export VITE_API_URL=https://api.yourdomain.com

pnpm build

或创建 .env.production 文件:

bash
# apps/web/.env.production
VITE_API_URL=https://api.yourdomain.com
VITE_AUTH_PORTAL_URL=https://auth.yourdomain.com

# apps/auth-portal/.env.production
VITE_API_URL=https://api.yourdomain.com

2.3 使用 Nginx 部署

Nginx 配置示例

nginx
# Web 应用
server {
    listen 80;
    server_name app.yourdomain.com;

    root /var/www/fullstackpack/web/dist;
    index index.html;

    # SPA 路由支持
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 静态资源缓存
    location /assets {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

# 认证门户
server {
    listen 80;
    server_name auth.yourdomain.com;

    root /var/www/fullstackpack/auth-portal/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /assets {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

# API 代理(可选,如果前端和后端在同一服务器)
server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

2.4 使用 Node.js 静态服务器(开发/测试)

bash
# 安装 serve
npm install -g serve

# 启动 Web 应用
serve -s apps/web/dist -l 8000

# 启动认证门户
serve -s apps/auth-portal/dist -l 7777

3. 完整部署示例

3.1 使用 Docker Compose

创建 docker-compose.yml

yaml
version: '3.8'

services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: fullstackpack
      POSTGRES_PASSWORD: your-password
      POSTGRES_DB: fullstackpack
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  api:
    build:
      context: .
      dockerfile: apps/server/Dockerfile
    environment:
      DATABASE_URL: postgresql://fullstackpack:your-password@postgres:5432/fullstackpack
      JWT_SECRET: your-secret-key-at-least-32-characters-long
      NODE_ENV: production
      SERVER_PORT: 3000
      SERVER_HOST: 0.0.0.0
    ports:
      - "3000:3000"
    depends_on:
      - postgres

  nginx:
    image: nginx:alpine
    volumes:
      - ./apps/web/dist:/usr/share/nginx/html/web:ro
      - ./apps/auth-portal/dist:/usr/share/nginx/html/auth:ro
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - api

volumes:
  postgres_data:

3.2 使用 PM2 部署

ecosystem.config.js

javascript
module.exports = {
  apps: [
    {
      name: 'fullstackpack-api',
      script: './apps/server/dist/server.js',
      cwd: '/path/to/fullstackpack',
      env: {
        NODE_ENV: 'production',
        DATABASE_URL: 'postgresql://...',
        JWT_SECRET: '...',
        SERVER_PORT: 3000,
        SERVER_HOST: '0.0.0.0',
      },
      instances: 'max',
      exec_mode: 'cluster',
    },
  ],
}

启动:

bash
pm2 start ecosystem.config.js
pm2 save
pm2 startup

环境变量对比

Cloudflare Workers(后端)

bash
# 必需
ACCELERATE_URL=prisma://accelerate.prisma.io/?api_key=...
JWT_SECRET=...

# 可选
NODE_ENV=production
CORS_ORIGIN=https://your-frontend.com
JWT_EXPIRES_IN=7d

自托管 Node.js(后端)

bash
# 必需
DATABASE_URL=postgresql://user:password@host:5432/dbname
JWT_SECRET=...

# 可选
NODE_ENV=production
SERVER_PORT=3000
SERVER_HOST=0.0.0.0
CORS_ORIGIN=https://your-frontend.com
JWT_EXPIRES_IN=7d

前端(两种方式相同)

bash
VITE_API_URL=https://api.yourdomain.com
VITE_AUTH_PORTAL_URL=https://auth.yourdomain.com

数据库连接差异

Cloudflare Workers

  • 必须使用: Prisma Accelerate(通过 HTTP API)
  • 原因: Workers 不支持 TCP 连接

自托管 Node.js

  • 推荐使用: DATABASE_URL + Prisma Adapter(直接 TCP 连接)
  • 也可以使用: Prisma Accelerate(如果需要)

性能对比

特性Cloudflare Workers自托管 Node.js
延迟边缘计算,全球低延迟取决于服务器位置
扩展性自动扩展需要手动配置
成本按请求计费固定服务器成本
数据库连接必须使用 Accelerate直接 TCP 连接
维护无需维护需要服务器维护

推荐方案

  • 小型项目/原型: Cloudflare 部署(简单、快速)
  • 大型项目/企业: 自托管(更多控制、成本可控)
  • 混合方案: 前端 Cloudflare Pages + 后端自托管

注意事项

  1. CORS 配置: 确保后端 CORS 设置允许前端域名
  2. HTTPS: 生产环境必须使用 HTTPS
  3. 环境变量: 不要在代码中硬编码敏感信息
  4. 数据库迁移: 生产环境使用 prisma migrate deploy 而不是 db:push
  5. 日志: 配置适当的日志收集和监控

Released under the MIT License.