diff --git a/.env.production.example b/.env.production.example new file mode 100644 index 0000000..0bd58b6 --- /dev/null +++ b/.env.production.example @@ -0,0 +1,12 @@ +# 生产环境配置 +# 复制此文件为 .env.production 并修改配置 + +NODE_ENV=production +PORT=3000 + +# 数据库配置 +DB_HOST=localhost +DB_PORT=3306 +DB_USERNAME=your_db_username +DB_PASSWORD=your_db_password +DB_DATABASE=meme_mind diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..993b833 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,94 @@ +#!/bin/bash + +# 部署脚本 - 将代码部署到远程服务器 +# 用法: pnpm run deploy + +set -e + +# 配置变量 +SERVER_IP="119.91.211.52" +SERVER_USER="root" +REMOTE_DIR="/var/www/MemeMind-Server" +APP_NAME="mememind-server" + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} MemeMind Server 部署脚本${NC}" +echo -e "${GREEN}========================================${NC}" + +# 1. 本地构建 +echo -e "\n${YELLOW}[1/4] 构建项目...${NC}" +pnpm run build +echo -e "${GREEN}✓ 构建完成${NC}" + +# 2. 同步文件到服务器 +echo -e "\n${YELLOW}[2/4] 同步文件到服务器 ${SERVER_IP}...${NC}" +rsync -avz --delete \ + --exclude 'node_modules' \ + --exclude '.git' \ + --exclude 'coverage' \ + --exclude '.env.local' \ + --exclude '*.log' \ + --exclude '.DS_Store' \ + ./dist/ ${SERVER_USER}@${SERVER_IP}:${REMOTE_DIR}/dist/ + +rsync -avz \ + --exclude 'node_modules' \ + package.json \ + pnpm-lock.yaml \ + ecosystem.config.js \ + ${SERVER_USER}@${SERVER_IP}:${REMOTE_DIR}/ + +echo -e "${GREEN}✓ 文件同步完成${NC}" + +# 3. 在服务器上安装依赖并重启 +echo -e "\n${YELLOW}[3/4] 在服务器上安装依赖...${NC}" +ssh ${SERVER_USER}@${SERVER_IP} << 'ENDSSH' +cd /var/www/MemeMind-Server + +# 检查 pnpm 是否安装 +if ! command -v pnpm &> /dev/null; then + echo "安装 pnpm..." + npm install -g pnpm +fi + +# 安装依赖 +pnpm install --prod + +echo "依赖安装完成" +ENDSSH +echo -e "${GREEN}✓ 依赖安装完成${NC}" + +# 4. 重启 PM2 +echo -e "\n${YELLOW}[4/4] 重启 PM2 服务...${NC}" +ssh ${SERVER_USER}@${SERVER_IP} << ENDSSH +cd ${REMOTE_DIR} + +# 检查 PM2 是否已运行该应用 +if pm2 list | grep -q "${APP_NAME}"; then + echo "重载应用 ${APP_NAME}..." + pm2 reload ${APP_NAME} +else + echo "启动应用 ${APP_NAME}..." + pm2 start ecosystem.config.js +fi + +# 保存 PM2 配置 +pm2 save + +echo "" +echo "PM2 状态:" +pm2 list +ENDSSH +echo -e "${GREEN}✓ 服务重启完成${NC}" + +echo -e "\n${GREEN}========================================${NC}" +echo -e "${GREEN} 部署成功!${NC}" +echo -e "${GREEN}========================================${NC}" +echo -e "API 地址: http://${SERVER_IP}:3000/api" +echo -e "Swagger 文档: http://${SERVER_IP}:3000/api/docs" diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..b0e94fc --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,27 @@ +module.exports = { + apps: [ + { + name: 'mememind-server', + script: 'dist/main.js', + instances: 2, + exec_mode: 'cluster', + autorestart: true, + watch: false, + max_memory_restart: '1G', + env: { + NODE_ENV: 'production', + PORT: 3000, + }, + env_production: { + NODE_ENV: 'production', + PORT: 3000, + }, + error_file: './logs/error.log', + out_file: './logs/out.log', + log_file: './logs/combined.log', + time: true, + merge_logs: true, + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + }, + ], +}; diff --git a/package.json b/package.json index c1a7de1..01d54fa 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json" + "test:e2e": "jest --config ./test/jest-e2e.json", + "deploy": "bash deploy.sh" }, "dependencies": { "@nestjs/common": "^11.0.1", diff --git a/src/config/config.module.ts b/src/config/config.module.ts index 6877c5b..2ea12b4 100644 --- a/src/config/config.module.ts +++ b/src/config/config.module.ts @@ -10,7 +10,7 @@ import { validateEnvironment } from './env.validation'; isGlobal: true, load: [databaseConfig], validate: validateEnvironment, - envFilePath: ['.env.local', '.env'], + envFilePath: ['.env.local', '.env.production', '.env'], }), ], exports: [ConfigModule],