部署概览
本项目支持多种部署方式:
- Vercel 部署(推荐,最简单)
- Docker 部署(适合自托管)
- 传统服务器部署(适合企业)
方案一:Vercel 部署(推荐)
为什么选择 Vercel?
- ✅ 免费额度充足(100GB 流量/月)
- ✅ 自动 HTTPS 和 CDN
- ✅ 与 Next.js 完美集成
- ✅ Git 提交自动部署
- ✅ 零配置,开箱即用
部署步骤
1. 准备工作
# 确保代码已提交到 Git
git add .
git commit -m "Ready for deployment"
git push origin main
2. 连接 Vercel
方式 A:通过 Vercel CLI(推荐)
# 安装 Vercel CLI
npm i -g vercel
# 登录
vercel login
# 部署
vercel
# 按提示操作:
# ? Set up and deploy "~/ai-content-studio"? [Y/n] y
# ? Which scope do you want to deploy to? Your Name
# ? Link to existing project? [y/N] n
# ? What's your project's name? ai-content-studio
# ? In which directory is your code located? ./
方式 B:通过 Vercel Dashboard
- 访问 https://vercel.com/new
- 导入 GitHub 仓库
- 配置项目名称
- 点击 Deploy
3. 配置环境变量
在 Vercel Dashboard 中设置环境变量:
Settings → Environment Variables
必需的环境变量:
# AI 服务
AI_PROVIDER=deepseek
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxx
DEEPSEEK_BASE_URL=https://api.deepseek.com
# OpenAI(备用)
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxx
# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
# 应用配置
NEXT_PUBLIC_APP_URL=https://your-app.vercel.app
NODE_ENV=production
重要提示:
NEXT_PUBLIC_开头的变量会暴露到前端- 不要在前端使用
SERVICE_ROLE_KEY - 设置后需要重新部署才能生效
4. 自定义域名(可选)
Settings → Domains → Add Domain
输入你的域名(例如:my-ai-app.com),按照提示配置 DNS:
Type: CNAME
Name: @
Value: cname.vercel-dns.com
等待 DNS 生效(通常 10-30 分钟),然后访问你的域名!
5. 验证部署
访问部署的 URL,检查:
- ✅ 页面正常显示
- ✅ 可以登录注册
- ✅ AI 生成功能正常
- ✅ 数据能够保存
6. 自动部署配置
Vercel 默认会监听 Git 仓库:
main分支推送 → 自动部署到生产环境- 其他分支推送 → 自动部署到预览环境
自定义部署分支:
Settings → Git → Production Branch
方案二:Docker 部署
Dockerfile
创建 Dockerfile:
# ==================== 构建阶段 ====================
FROM node:18-alpine AS builder
# 设置工作目录
WORKDIR /app
# 复制 package 文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制源代码
COPY . .
# 构建应用
RUN npm run build
# ==================== 运行阶段 ====================
FROM node:18-alpine AS runner
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV NODE_ENV=production
# 创建非 root 用户
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# 复制必要文件
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
# 更改文件所有者
RUN chown -R nextjs:nodejs /app
# 切换到非 root 用户
USER nextjs
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
docker-compose.yml
version: '3.8'
services:
# Next.js 应用
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
# AI 配置
- AI_PROVIDER=deepseek
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
- DEEPSEEK_BASE_URL=https://api.deepseek.com
# Supabase 配置
- NEXT_PUBLIC_SUPABASE_URL=${SUPABASE_URL}
- NEXT_PUBLIC_SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
- SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_KEY}
# 应用配置
- NEXT_PUBLIC_APP_URL=http://localhost:3000
- NODE_ENV=production
restart: unless-stopped
networks:
- app-network
# Nginx 反向代理(可选)
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
restart: unless-stopped
networks:
- app-network
networks:
app-network:
driver: bridge
部署步骤
# 1. 创建 .env 文件
cat > .env << 'EOF'
DEEPSEEK_API_KEY=sk-xxxxxxxx
SUPABASE_URL=https://xxxxx.supabase.co
SUPABASE_ANON_KEY=eyJhbGc...
SUPABASE_SERVICE_KEY=eyJhbGc...
EOF
# 2. 构建镜像
docker-compose build
# 3. 启动服务
docker-compose up -d
# 4. 查看日志
docker-compose logs -f
# 5. 停止服务
docker-compose down
Nginx 配置(可选)
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream app {
server app:3000;
}
server {
listen 80;
server_name your-domain.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# 反向代理
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
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;
}
# 静态资源缓存
location /_next/static {
proxy_pass http://app;
add_header Cache-Control "public, max-age=31536000, immutable";
}
}
}
方案三:传统服务器部署
系统要求
- Ubuntu 20.04+ / CentOS 7+
- Node.js 18+
- Nginx
- PM2(进程管理)
部署步骤
1. 服务器准备
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装 Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# 安装 Nginx
sudo apt install -y nginx
# 安装 PM2
sudo npm install -g pm2
2. 上传代码
# 在本地打包
npm run build
tar -czf dist.tar.gz .next public package.json package-lock.json
# 上传到服务器
scp dist.tar.gz user@your-server:/var/www/ai-studio/
# 在服务器上解压
ssh user@your-server
cd /var/www/ai-studio
tar -xzf dist.tar.gz
npm ci --only=production
3. 配置环境变量
# 创建 .env.local
cat > .env.local << 'EOF'
AI_PROVIDER=deepseek
DEEPSEEK_API_KEY=sk-xxxxxxxx
DEEPSEEK_BASE_URL=https://api.deepseek.com
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
NEXT_PUBLIC_APP_URL=https://your-domain.com
NODE_ENV=production
EOF
# 设置权限
chmod 600 .env.local
4. PM2 配置
创建 ecosystem.config.js:
module.exports = {
apps: [{
name: 'ai-content-studio',
script: 'node_modules/next/dist/bin/next',
args: 'start',
cwd: '/var/www/ai-studio',
instances: 'max', // 使用所有 CPU 核心
exec_mode: 'cluster', // 集群模式
env: {
NODE_ENV: 'production',
PORT: 3000,
},
error_file: '/var/log/ai-studio/error.log',
out_file: '/var/log/ai-studio/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss',
merge_logs: true,
autorestart: true,
max_memory_restart: '1G', // 内存超过 1G 自动重启
watch: false,
}],
};
5. 启动应用
# 创建日志目录
sudo mkdir -p /var/log/ai-studio
sudo chown $USER:$USER /var/log/ai-studio
# 启动应用
pm2 start ecosystem.config.js
# 查看状态
pm2 status
# 查看日志
pm2 logs
# 设置开机自启
pm2 startup
pm2 save
6. Nginx 配置
# 创建配置文件
sudo nano /etc/nginx/sites-available/ai-studio
# 添加配置
server {
listen 80;
server_name your-domain.com;
# 反向代理到 Next.js
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
# 启用站点
sudo ln -s /etc/nginx/sites-available/ai-studio /etc/nginx/sites-enabled/
# 测试配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
7. SSL 证书(Let's Encrypt)
# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d your-domain.com
# 自动续期
sudo certbot renew --dry-run
性能优化
1. Next.js 配置优化
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// 生产环境优化
compress: true, // 启用 gzip 压缩
poweredByHeader: false, // 移除 X-Powered-By header
reactStrictMode: true, // 严格模式
// 输出优化
output: 'standalone', // 独立输出,减小部署体积
// 图片优化
images: {
formats: ['image/avif', 'image/webp'], // 使用现代格式
minimumCacheTTL: 60, // 缓存时间
},
// 实验性功能
experimental: {
optimizeCss: true, // CSS 优化
optimizePackageImports: ['antd'], // 包导入优化
},
};
module.exports = nextConfig;
2. 数据库连接池
// src/lib/db/supabase.ts
import { createClient } from '@supabase/supabase-js';
// 创建单例客户端
let supabaseInstance: ReturnType<typeof createClient> | null = null;
export function getSupabaseClient() {
if (!supabaseInstance) {
supabaseInstance = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
auth: {
persistSession: false, // 服务端不需要持久化
},
db: {
schema: 'public',
},
global: {
headers: {
'x-application-name': 'ai-content-studio',
},
},
}
);
}
return supabaseInstance;
}
3. Redis 缓存(可选)
// src/lib/cache/redis.ts
import Redis from 'ioredis';
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD,
retryStrategy(times) {
return Math.min(times * 50, 2000);
},
});
export async function getCached<T>(
key: string,
fetcher: () => Promise<T>,
ttl: number = 3600
): Promise<T> {
// 尝试从缓存获取
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached);
}
// 缓存未命中,调用 fetcher
const data = await fetcher();
// 存入缓存
await redis.setex(key, ttl, JSON.stringify(data));
return data;
}
监控和日志
1. Vercel Analytics
// src/app/layout.tsx
import { Analytics } from '@vercel/analytics/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
</body>
</html>
);
}
2. Sentry 错误追踪
# 安装 Sentry
npm install @sentry/nextjs
// sentry.client.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 1.0,
});
3. 自定义日志
// src/lib/logger.ts
import winston from 'winston';
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple(),
}));
}
export default logger;
常见问题
Q1: 部署后 API 调用失败
可能原因:
- 环境变量未设置
- API Key 错误
- 网络限制
解决方案:
# 检查环境变量
vercel env ls
# 查看日志
vercel logs
# 本地测试
vercel dev
Q2: 数据库连接失败
可能原因:
- Supabase URL 或 Key 错误
- RLS 策略配置问题
解决方案:
// 测试连接
const { data, error } = await supabase
.from('projects')
.select('count')
.single();
console.log('连接测试:', { data, error });
Q3: 构建失败
可能原因:
- 依赖版本冲突
- TypeScript 类型错误
解决方案:
# 清理缓存
rm -rf .next node_modules
npm install
npm run build
# 查看详细错误
npm run build -- --debug
部署检查清单
部署前:
- 所有测试通过
- 生产环境配置完成
- 环境变量已设置
- 数据库迁移完成
- API Keys 已获取
部署后:
- 网站可以正常访问
- 用户可以注册登录
- AI 功能正常工作
- 数据可以正常保存
- 错误日志正常记录
- 性能指标在合理范围
- SSL 证书有效
面试要点
部署经验讲解
简短版:
"我使用 Vercel 部署项目,因为它与 Next.js 集成得最好。
配置环境变量后,git push 就自动部署,非常方便。
同时我也准备了 Docker 方案,方便自托管。"
详细版:
"我支持多种部署方式:
1. Vercel(生产环境):
- 自动 CI/CD
- 全球 CDN
- 零配置 HTTPS
2. Docker(自托管):
- 多阶段构建减小镜像
- 使用 docker-compose 管理
- Nginx 做反向代理
3. PM2(传统服务器):
- 集群模式利用多核
- 自动重启保证可用性
- 日志管理方便调试
还做了性能优化:
- 启用 standalone 输出
- 配置图片优化
- 使用 Redis 缓存
- 集成监控和日志