自托管部署
概述
自托管部署允许你在自有服务器上运行 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 install1.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.com1.4 数据库迁移
bash
# 生成 Prisma Client
pnpm db:generate
# 推送数据库 schema(开发环境)
pnpm db:push
# 或使用 migrations(生产环境推荐)
npx prisma migrate deploy1.5 构建和启动
bash
# 构建
pnpm build
# 启动(使用 Node.js)
pnpm start
# 或使用 PM2(推荐生产环境)
pm2 start dist/server.js --name fullstackpack-api1.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-api2. 前端部署
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.com2.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 77773. 完整部署示例
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 + 后端自托管
注意事项
- CORS 配置: 确保后端 CORS 设置允许前端域名
- HTTPS: 生产环境必须使用 HTTPS
- 环境变量: 不要在代码中硬编码敏感信息
- 数据库迁移: 生产环境使用
prisma migrate deploy而不是db:push - 日志: 配置适当的日志收集和监控