feat: 双环境自动化部署(生产 + 测试)
- 新增 docker-compose.prod.yml / docker-compose.test.yml 双环境配置 - 新增 docker-compose.gateway.yml Nginx 网关按域名路由 - 新增 Dockerfile.website 官网镜像构建 - 新增 gateway.conf 支持 8 个域名路由 - 更新 .gitlab-ci.yml 支持 prod/test 双分支自动部署 - 更新 Makefile 新增 prod-/test-/gateway- 快捷命令 - 新增 scripts/setup-server.sh 服务器一键初始化脚本 - 修复 Nginx 配置服务名不匹配问题 - 修复前端 Dockerfile 缺少 packages/ 导致构建失败 - 删除旧的 docker-compose.yml Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+47
-7
@@ -6,12 +6,13 @@ stages:
|
|||||||
variables:
|
variables:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
|
|
||||||
# 仅 prod 分支触发
|
# prod 和 test 分支触发
|
||||||
workflow:
|
workflow:
|
||||||
rules:
|
rules:
|
||||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
when: never
|
when: never
|
||||||
- if: $CI_COMMIT_BRANCH == "prod"
|
- if: $CI_COMMIT_BRANCH == "prod"
|
||||||
|
- if: $CI_COMMIT_BRANCH == "test"
|
||||||
|
|
||||||
# pnpm store 缓存
|
# pnpm store 缓存
|
||||||
cache:
|
cache:
|
||||||
@@ -86,6 +87,20 @@ build_platform:
|
|||||||
- apps/platform-admin/dist/
|
- apps/platform-admin/dist/
|
||||||
expire_in: 1 hour
|
expire_in: 1 hour
|
||||||
|
|
||||||
|
build_website:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- rent-deploy
|
||||||
|
needs: [install_dependencies]
|
||||||
|
script:
|
||||||
|
- npm install -g pnpm
|
||||||
|
- pnpm config set store-dir .pnpm-store
|
||||||
|
- pnpm --filter @rent/official-website build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- apps/official-website/out/
|
||||||
|
expire_in: 1 hour
|
||||||
|
|
||||||
# ==================== DEPLOY ====================
|
# ==================== DEPLOY ====================
|
||||||
deploy_production:
|
deploy_production:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
@@ -95,17 +110,42 @@ deploy_production:
|
|||||||
- build_server
|
- build_server
|
||||||
- build_merchant
|
- build_merchant
|
||||||
- build_platform
|
- build_platform
|
||||||
|
- build_website
|
||||||
script:
|
script:
|
||||||
- echo "部署到生产环境..."
|
- echo "部署到生产环境..."
|
||||||
- cd deploy/docker
|
- cd deploy/docker
|
||||||
- docker-compose down --remove-orphans
|
- docker-compose -f docker-compose.prod.yml down --remove-orphans
|
||||||
- docker-compose build --parallel
|
- docker-compose -f docker-compose.prod.yml build --parallel
|
||||||
- docker-compose up -d
|
- docker-compose -f docker-compose.prod.yml up -d
|
||||||
- docker image prune -f
|
- docker image prune -f
|
||||||
- echo "等待服务启动..."
|
- echo "等待服务启动..."
|
||||||
- sleep 10
|
- sleep 10
|
||||||
- docker-compose ps
|
- docker-compose -f docker-compose.prod.yml ps
|
||||||
environment:
|
environment:
|
||||||
name: production
|
name: production
|
||||||
only:
|
rules:
|
||||||
- prod
|
- if: $CI_COMMIT_BRANCH == "prod"
|
||||||
|
|
||||||
|
deploy_test:
|
||||||
|
stage: deploy
|
||||||
|
tags:
|
||||||
|
- rent-deploy
|
||||||
|
needs:
|
||||||
|
- build_server
|
||||||
|
- build_merchant
|
||||||
|
- build_platform
|
||||||
|
- build_website
|
||||||
|
script:
|
||||||
|
- echo "部署到测试环境..."
|
||||||
|
- cd deploy/docker
|
||||||
|
- docker-compose -f docker-compose.test.yml down --remove-orphans
|
||||||
|
- docker-compose -f docker-compose.test.yml build --parallel
|
||||||
|
- docker-compose -f docker-compose.test.yml up -d
|
||||||
|
- docker image prune -f
|
||||||
|
- echo "等待服务启动..."
|
||||||
|
- sleep 10
|
||||||
|
- docker-compose -f docker-compose.test.yml ps
|
||||||
|
environment:
|
||||||
|
name: test
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == "test"
|
||||||
|
|||||||
@@ -1,43 +1,100 @@
|
|||||||
.PHONY: help install build up down restart logs ps deploy clean
|
.PHONY: help install \
|
||||||
|
prod-build prod-up prod-down prod-restart prod-logs prod-logs-server prod-ps prod-deploy \
|
||||||
|
test-build test-up test-down test-restart test-logs test-logs-server test-ps test-deploy \
|
||||||
|
gateway-up gateway-down gateway-reload \
|
||||||
|
init deploy clean
|
||||||
|
|
||||||
DOCKER_COMPOSE = docker-compose -f deploy/docker/docker-compose.yml
|
DOCKER_PROD = docker-compose -f deploy/docker/docker-compose.prod.yml
|
||||||
|
DOCKER_TEST = docker-compose -f deploy/docker/docker-compose.test.yml
|
||||||
|
DOCKER_GATEWAY = docker-compose -f deploy/docker/docker-compose.gateway.yml
|
||||||
|
|
||||||
help: ## 显示帮助信息
|
help: ## 显示帮助信息
|
||||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
|
||||||
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
install: ## 安装依赖
|
install: ## 安装依赖
|
||||||
npm install -g pnpm
|
npm install -g pnpm
|
||||||
pnpm install
|
pnpm install
|
||||||
|
|
||||||
build: ## 构建所有 Docker 镜像
|
# ===== 生产环境 =====
|
||||||
$(DOCKER_COMPOSE) build --parallel
|
prod-build: ## 构建生产环境镜像
|
||||||
|
$(DOCKER_PROD) build --parallel
|
||||||
|
|
||||||
up: ## 启动所有服务
|
prod-up: ## 启动生产环境
|
||||||
$(DOCKER_COMPOSE) up -d
|
$(DOCKER_PROD) up -d
|
||||||
|
|
||||||
down: ## 停止所有服务
|
prod-down: ## 停止生产环境
|
||||||
$(DOCKER_COMPOSE) down
|
$(DOCKER_PROD) down
|
||||||
|
|
||||||
restart: ## 重启所有服务
|
prod-restart: ## 重启生产环境
|
||||||
$(DOCKER_COMPOSE) restart
|
$(DOCKER_PROD) restart
|
||||||
|
|
||||||
logs: ## 查看所有服务日志
|
prod-logs: ## 查看生产环境日志
|
||||||
$(DOCKER_COMPOSE) logs -f --tail=100
|
$(DOCKER_PROD) logs -f --tail=100
|
||||||
|
|
||||||
logs-server: ## 查看后端服务日志
|
prod-logs-server: ## 查看生产环境后端日志
|
||||||
$(DOCKER_COMPOSE) logs -f --tail=100 server
|
$(DOCKER_PROD) logs -f --tail=100 server
|
||||||
|
|
||||||
ps: ## 查看运行中的容器
|
prod-ps: ## 查看生产环境容器
|
||||||
$(DOCKER_COMPOSE) ps
|
$(DOCKER_PROD) ps
|
||||||
|
|
||||||
deploy: down build up ## 完整部署(停止 → 构建 → 启动)
|
prod-deploy: prod-down prod-build prod-up ## 完整部署生产环境
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "部署完成!"
|
@echo "生产环境部署完成!"
|
||||||
@echo " 商家后台: http://localhost:8081"
|
@echo " API: http://api.pinzhuhui.com"
|
||||||
@echo " 平台后台: http://localhost:8082"
|
@echo " 官网: http://www.pinzhuhui.com"
|
||||||
@echo " API 服务: http://localhost:3000"
|
@echo " 商家后台: http://merchant.pinzhuhui.com"
|
||||||
|
@echo " 平台后台: http://platform-admin.pinzhuhui.com"
|
||||||
|
|
||||||
|
# ===== 测试环境 =====
|
||||||
|
test-build: ## 构建测试环境镜像
|
||||||
|
$(DOCKER_TEST) build --parallel
|
||||||
|
|
||||||
|
test-up: ## 启动测试环境
|
||||||
|
$(DOCKER_TEST) up -d
|
||||||
|
|
||||||
|
test-down: ## 停止测试环境
|
||||||
|
$(DOCKER_TEST) down
|
||||||
|
|
||||||
|
test-restart: ## 重启测试环境
|
||||||
|
$(DOCKER_TEST) restart
|
||||||
|
|
||||||
|
test-logs: ## 查看测试环境日志
|
||||||
|
$(DOCKER_TEST) logs -f --tail=100
|
||||||
|
|
||||||
|
test-logs-server: ## 查看测试环境后端日志
|
||||||
|
$(DOCKER_TEST) logs -f --tail=100 server
|
||||||
|
|
||||||
|
test-ps: ## 查看测试环境容器
|
||||||
|
$(DOCKER_TEST) ps
|
||||||
|
|
||||||
|
test-deploy: test-down test-build test-up ## 完整部署测试环境
|
||||||
|
@echo ""
|
||||||
|
@echo "测试环境部署完成!"
|
||||||
|
@echo " API: http://api-test.pinzhuhui.com"
|
||||||
|
@echo " 官网: http://test.pinzhuhui.com"
|
||||||
|
@echo " 商家后台: http://merchant-test.pinzhuhui.com"
|
||||||
|
@echo " 平台后台: http://platform-admin-test.pinzhuhui.com"
|
||||||
|
|
||||||
|
# ===== 网关 =====
|
||||||
|
gateway-up: ## 启动网关
|
||||||
|
$(DOCKER_GATEWAY) up -d
|
||||||
|
|
||||||
|
gateway-down: ## 停止网关
|
||||||
|
$(DOCKER_GATEWAY) down
|
||||||
|
|
||||||
|
gateway-reload: ## 重载网关配置
|
||||||
|
docker exec rent-gateway nginx -s reload
|
||||||
|
|
||||||
|
# ===== 快捷命令 =====
|
||||||
|
init: gateway-up ## 首次初始化(启动网关 + 创建网络)
|
||||||
|
@echo "网络已创建,网关已启动。"
|
||||||
|
@echo "接下来运行 make prod-deploy 或 make test-deploy"
|
||||||
|
|
||||||
|
deploy: prod-deploy ## 别名:部署生产环境
|
||||||
|
|
||||||
clean: ## 清理所有容器、数据卷和悬空镜像
|
clean: ## 清理所有容器、数据卷和悬空镜像
|
||||||
$(DOCKER_COMPOSE) down -v
|
$(DOCKER_PROD) down -v
|
||||||
|
$(DOCKER_TEST) down -v
|
||||||
|
$(DOCKER_GATEWAY) down
|
||||||
docker image prune -f
|
docker image prune -f
|
||||||
|
|||||||
+175
-119
@@ -1,102 +1,139 @@
|
|||||||
# 部署指南
|
# 部署指南
|
||||||
|
|
||||||
|
## 架构概览
|
||||||
|
|
||||||
|
```
|
||||||
|
Internet → Gateway Nginx (80/443)
|
||||||
|
├─ rent-prod 网络
|
||||||
|
│ ├─ rent-prod-mysql (3306)
|
||||||
|
│ ├─ rent-prod-redis (6379)
|
||||||
|
│ ├─ rent-prod-server (3000)
|
||||||
|
│ ├─ rent-prod-merchant (8081→80)
|
||||||
|
│ ├─ rent-prod-platform (8082→80)
|
||||||
|
│ └─ rent-prod-website (8083→80)
|
||||||
|
└─ rent-test 网络
|
||||||
|
├─ rent-test-mysql (3307→3306)
|
||||||
|
├─ rent-test-redis (6380→6379)
|
||||||
|
├─ rent-test-server (3001→3000)
|
||||||
|
├─ rent-test-merchant (9081→80)
|
||||||
|
├─ rent-test-platform (9082→80)
|
||||||
|
└─ rent-test-website (9083→80)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 域名规划
|
||||||
|
|
||||||
|
| 环境 | 用途 | 域名 |
|
||||||
|
|------|------|------|
|
||||||
|
| 生产 | API | api.pinzhuhui.com |
|
||||||
|
| 生产 | 官网 | www.pinzhuhui.com |
|
||||||
|
| 生产 | 商家后台 | merchant.pinzhuhui.com |
|
||||||
|
| 生产 | 平台后台 | platform-admin.pinzhuhui.com |
|
||||||
|
| 测试 | API | api-test.pinzhuhui.com |
|
||||||
|
| 测试 | 官网 | test.pinzhuhui.com |
|
||||||
|
| 测试 | 商家后台 | merchant-test.pinzhuhui.com |
|
||||||
|
| 测试 | 平台后台 | platform-admin-test.pinzhuhui.com |
|
||||||
|
|
||||||
## 目录结构
|
## 目录结构
|
||||||
|
|
||||||
```
|
```text
|
||||||
deploy/
|
deploy/
|
||||||
├── docker/
|
├── docker/
|
||||||
│ ├── docker-compose.yml # Docker Compose 编排文件
|
│ ├── docker-compose.prod.yml # 生产环境
|
||||||
│ ├── Dockerfile.server # 后端服务镜像
|
│ ├── docker-compose.test.yml # 测试环境
|
||||||
│ ├── Dockerfile.merchant # 商家后台镜像
|
│ ├── docker-compose.gateway.yml # Gateway 网关
|
||||||
│ ├── Dockerfile.platform # 平台后台镜像
|
│ ├── Dockerfile.server # 后端镜像
|
||||||
│ └── .env.example # 环境变量模板
|
│ ├── Dockerfile.merchant # 商家后台镜像
|
||||||
└── nginx/
|
│ ├── Dockerfile.platform # 平台后台镜像
|
||||||
├── api.conf # API 反向代理配置
|
│ ├── Dockerfile.website # 官网镜像
|
||||||
├── merchant.conf # 商家后台 Nginx 配置
|
│ ├── .env.example # 环境变量模板
|
||||||
└── platform.conf # 平台后台 Nginx 配置
|
│ └── .env # 实际配置(不入仓库)
|
||||||
```
|
├── nginx/
|
||||||
|
│ ├── gateway/gateway.conf # Gateway 域名路由
|
||||||
## 服务端口
|
│ ├── api.conf # 后端 Nginx 配置
|
||||||
|
│ ├── merchant.conf # 商家后台 Nginx 配置
|
||||||
| 服务 | 端口 | 说明 |
|
│ └── platform.conf # 平台后台 Nginx 配置
|
||||||
|------|------|------|
|
scripts/
|
||||||
| MySQL | 3306 | 数据库 |
|
│ └── setup-server.sh # 首次初始化脚本
|
||||||
| Redis | 6379 | 缓存 |
|
|
||||||
| Server | 3000 | 后端 API |
|
|
||||||
| Merchant Admin | 8081 | 商家管理后台 |
|
|
||||||
| Platform Admin | 8082 | 平台管理后台 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 一、快速部署(手动)
|
|
||||||
|
|
||||||
### 1. 配置环境变量
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd deploy/docker
|
|
||||||
cp .env.example .env
|
|
||||||
# 编辑 .env,填入真实的密码和密钥
|
|
||||||
vi .env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 构建并启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 方式一:使用 Makefile(推荐)
|
|
||||||
make deploy
|
|
||||||
|
|
||||||
# 方式二:直接使用 docker-compose
|
|
||||||
docker-compose -f deploy/docker/docker-compose.yml up -d --build
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 常用命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make help # 查看所有命令
|
|
||||||
make logs # 查看日志
|
|
||||||
make logs-server # 查看后端日志
|
|
||||||
make ps # 查看容器状态
|
|
||||||
make restart # 重启服务
|
|
||||||
make down # 停止服务
|
|
||||||
make clean # 清理所有数据(包括数据库)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 二、GitLab CI/CD 自动化部署
|
## 一、首次部署(服务器初始化)
|
||||||
|
|
||||||
|
### 第 1 步:运行初始化脚本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 将代码克隆到服务器
|
||||||
|
git clone <你的GitLab仓库地址> ~/rent-platform
|
||||||
|
cd ~/rent-platform
|
||||||
|
|
||||||
|
# 运行初始化(安装 Docker、创建网络、启动网关)
|
||||||
|
bash scripts/setup-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本会自动完成:
|
||||||
|
- 安装 Docker、Docker Compose、Git、pnpm
|
||||||
|
- 创建 `.env` 文件并提示你填写密码
|
||||||
|
- 创建 Docker 网络(rent-prod、rent-test)
|
||||||
|
- 启动 Gateway Nginx
|
||||||
|
|
||||||
|
### 第 2 步:配置 DNS
|
||||||
|
|
||||||
|
在你的域名管理面板添加 A 记录,将以下域名指向服务器 IP:
|
||||||
|
|
||||||
|
```text
|
||||||
|
# 生产环境
|
||||||
|
api.pinzhuhui.com → 服务器IP
|
||||||
|
www.pinzhuhui.com → 服务器IP
|
||||||
|
merchant.pinzhuhui.com → 服务器IP
|
||||||
|
platform-admin.pinzhuhui.com → 服务器IP
|
||||||
|
|
||||||
|
# 测试环境
|
||||||
|
api-test.pinzhuhui.com → 服务器IP
|
||||||
|
test.pinzhuhui.com → 服务器IP
|
||||||
|
merchant-test.pinzhuhui.com → 服务器IP
|
||||||
|
platform-admin-test.pinzhuhui.com → 服务器IP
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第 3 步:部署服务
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 部署生产环境
|
||||||
|
make prod-deploy
|
||||||
|
|
||||||
|
# 部署测试环境
|
||||||
|
make test-deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、GitLab CI/CD 自动化
|
||||||
|
|
||||||
### 前提条件
|
### 前提条件
|
||||||
|
|
||||||
- 服务器已安装 Docker 和 Docker Compose
|
- 服务器已运行初始化脚本
|
||||||
- 服务器已部署 GitLab 实例
|
- 代码已推送到 GitLab 仓库
|
||||||
- 项目代码已推送到 GitLab 仓库
|
|
||||||
|
|
||||||
### 第 1 步:安装 GitLab Runner
|
### 第 1 步:安装 GitLab Runner
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 添加 GitLab Runner 仓库
|
|
||||||
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
|
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
|
||||||
|
|
||||||
# 安装
|
|
||||||
sudo apt install gitlab-runner
|
sudo apt install gitlab-runner
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第 2 步:注册 Runner
|
### 第 2 步:注册 Runner
|
||||||
|
|
||||||
1. 在 GitLab 中打开项目 → **Settings → CI/CD → Runners**
|
1. GitLab → **Settings → CI/CD → Runners** → 复制 token
|
||||||
2. 复制 registration token
|
2. 在服务器执行:
|
||||||
3. 在服务器上执行注册:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo gitlab-runner register
|
sudo gitlab-runner register
|
||||||
```
|
```
|
||||||
|
|
||||||
按提示填写:
|
|
||||||
|
|
||||||
| 项目 | 值 |
|
| 项目 | 值 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| GitLab URL | `http://你的GitLab域名/` |
|
| GitLab URL | `http://你的GitLab地址/` |
|
||||||
| Token | 从 Settings 页面复制的 token |
|
| Token | 从页面复制 |
|
||||||
| Description | `rent-deploy-runner` |
|
| Description | `rent-deploy-runner` |
|
||||||
| Tags | `rent-deploy` |
|
| Tags | `rent-deploy` |
|
||||||
| Executor | `shell` |
|
| Executor | `shell` |
|
||||||
@@ -104,91 +141,110 @@ sudo gitlab-runner register
|
|||||||
### 第 3 步:配置 Runner 权限
|
### 第 3 步:配置 Runner 权限
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 让 gitlab-runner 用户可以执行 docker 命令
|
|
||||||
sudo usermod -aG docker gitlab-runner
|
sudo usermod -aG docker gitlab-runner
|
||||||
|
|
||||||
# 全局安装 pnpm
|
|
||||||
sudo -u gitlab-runner npm install -g pnpm
|
sudo -u gitlab-runner npm install -g pnpm
|
||||||
|
|
||||||
# 验证
|
|
||||||
sudo -u gitlab-runner docker ps
|
|
||||||
sudo -u gitlab-runner pnpm --version
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 第 4 步:配置 CI/CD 变量
|
### 第 4 步:配置 CI/CD 变量
|
||||||
|
|
||||||
在 GitLab 中打开 **Settings → CI/CD → Variables**,添加:
|
GitLab → **Settings → CI/CD → Variables**:
|
||||||
|
|
||||||
| 变量名 | 说明 | 勾选 Masked |
|
| 变量名 | 说明 | Masked |
|
||||||
|--------|------|-------------|
|
|--------|------|--------|
|
||||||
| `PROD_DB_PASSWORD` | MySQL root 密码 | ✅ |
|
| `PROD_DB_PASSWORD` | 生产数据库密码 | ✅ |
|
||||||
| `PROD_JWT_SECRET` | JWT 签名密钥 | ✅ |
|
| `PROD_JWT_SECRET` | 生产 JWT 密钥 | ✅ |
|
||||||
|
| `TEST_DB_PASSWORD` | 测试数据库密码 | ✅ |
|
||||||
|
| `TEST_JWT_SECRET` | 测试 JWT 密钥 | ✅ |
|
||||||
|
|
||||||
### 第 5 步:创建环境变量文件
|
### 第 5 步:推送代码触发部署
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 在服务器项目目录下创建 .env(只需一次)
|
# 推送 test 分支 → 自动部署测试环境
|
||||||
cd /path/to/repo/deploy/docker
|
git push origin test
|
||||||
cp .env.example .env
|
|
||||||
vi .env
|
|
||||||
# 填入 PROD_DB_PASSWORD 和 PROD_JWT_SECRET 的真实值
|
|
||||||
```
|
|
||||||
|
|
||||||
### 第 6 步:推送代码触发部署
|
# 推送 prod 分支 → 自动部署生产环境
|
||||||
|
|
||||||
```bash
|
|
||||||
git push origin prod
|
git push origin prod
|
||||||
```
|
```
|
||||||
|
|
||||||
推送后 GitLab 会自动运行流水线:
|
流水线:install → build(并行构建 4 个应用)→ deploy
|
||||||
|
|
||||||
1. **install** 阶段 — 安装依赖
|
|
||||||
2. **build** 阶段 — 并行构建 server / merchant / platform
|
|
||||||
3. **deploy** 阶段 — 停止旧服务 → 构建镜像 → 启动新服务
|
|
||||||
|
|
||||||
可以在 GitLab → **CI/CD → Pipelines** 页面查看实时日志。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 三、故障排查
|
## 三、常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make help # 查看所有命令
|
||||||
|
|
||||||
|
# 生产环境
|
||||||
|
make prod-deploy # 完整部署(停止→构建→启动)
|
||||||
|
make prod-logs # 查看日志
|
||||||
|
make prod-logs-server # 查看后端日志
|
||||||
|
make prod-ps # 查看容器状态
|
||||||
|
make prod-restart # 重启
|
||||||
|
|
||||||
|
# 测试环境
|
||||||
|
make test-deploy # 完整部署
|
||||||
|
make test-logs # 查看日志
|
||||||
|
make test-ps # 查看容器状态
|
||||||
|
make test-restart # 重启
|
||||||
|
|
||||||
|
# 网关
|
||||||
|
make gateway-up # 启动网关
|
||||||
|
make gateway-reload # 重载网关配置
|
||||||
|
|
||||||
|
# 其他
|
||||||
|
make clean # 清理所有环境(包括数据)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、故障排查
|
||||||
|
|
||||||
### 查看服务状态
|
### 查看服务状态
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make ps
|
make prod-ps # 生产环境
|
||||||
|
make test-ps # 测试环境
|
||||||
```
|
```
|
||||||
|
|
||||||
### 查看日志
|
### 查看日志
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 所有服务
|
make prod-logs # 生产环境所有日志
|
||||||
make logs
|
make prod-logs-server # 生产环境后端日志
|
||||||
|
make test-logs # 测试环境所有日志
|
||||||
|
|
||||||
# 仅后端
|
# 直接查看某个容器
|
||||||
make logs-server
|
docker logs rent-prod-server
|
||||||
|
docker logs rent-test-mysql
|
||||||
# 特定容器
|
|
||||||
docker logs rent-mysql
|
|
||||||
docker logs rent-redis
|
|
||||||
docker logs rent-server
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 数据库连接失败
|
### 数据库连接
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 检查 MySQL 是否就绪
|
# 生产环境
|
||||||
docker exec rent-mysql mysqladmin ping -h localhost -u root -p
|
docker exec -it rent-prod-mysql mysql -u root -p rent_platform
|
||||||
|
|
||||||
# 进入 MySQL 手动检查
|
# 测试环境
|
||||||
docker exec -it rent-mysql mysql -u root -p rent_platform
|
docker exec -it rent-test-mysql mysql -u root -p rent_platform
|
||||||
```
|
```
|
||||||
|
|
||||||
### 重建某个服务
|
### 重建单个服务
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 只重建后端
|
# 只重建生产环境后端
|
||||||
docker-compose -f deploy/docker/docker-compose.yml up -d --build server
|
docker-compose -f deploy/docker/docker-compose.prod.yml up -d --build server
|
||||||
|
|
||||||
# 只重建商家后台
|
# 只重建测试环境商家后台
|
||||||
docker-compose -f deploy/docker/docker-compose.yml up -d --build merchant-admin
|
docker-compose -f deploy/docker/docker-compose.test.yml up -d --build merchant-admin
|
||||||
|
```
|
||||||
|
|
||||||
|
### 网关问题
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查网关状态
|
||||||
|
docker logs rent-gateway
|
||||||
|
|
||||||
|
# 重载网关配置(修改了 gateway.conf 后)
|
||||||
|
make gateway-reload
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
# ===== 数据库 =====
|
# ===== 生产环境 =====
|
||||||
DB_PASSWORD=change_me_in_production
|
PROD_DB_PASSWORD=change_me_in_production
|
||||||
|
PROD_JWT_SECRET=change_me_in_production
|
||||||
|
|
||||||
# ===== JWT =====
|
# ===== 测试环境 =====
|
||||||
JWT_SECRET=change_me_in_production
|
TEST_DB_PASSWORD=change_me_in_test
|
||||||
|
TEST_JWT_SECRET=change_me_in_test
|
||||||
# ===== 服务配置 =====
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=3000
|
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# 官网 - Next.js 静态导出
|
||||||
|
FROM node:18-alpine AS website-builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
|
||||||
|
COPY packages/ ./packages/
|
||||||
|
COPY apps/official-website/ ./apps/official-website/
|
||||||
|
RUN npm install -g pnpm && pnpm install --frozen-lockfile
|
||||||
|
RUN cd apps/official-website && pnpm run build
|
||||||
|
|
||||||
|
FROM nginx:alpine AS website
|
||||||
|
COPY --from=website-builder /app/apps/official-website/out /usr/share/nginx/html
|
||||||
|
RUN echo 'server { \
|
||||||
|
listen 80; \
|
||||||
|
server_name _; \
|
||||||
|
root /usr/share/nginx/html; \
|
||||||
|
index index.html; \
|
||||||
|
location / { \
|
||||||
|
try_files $uri $uri.html $uri/ =404; \
|
||||||
|
} \
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { \
|
||||||
|
expires 30d; \
|
||||||
|
add_header Cache-Control "public, immutable"; \
|
||||||
|
} \
|
||||||
|
gzip on; \
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript; \
|
||||||
|
gzip_min_length 1024; \
|
||||||
|
}' > /etc/nginx/conf.d/default.conf
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
gateway:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: rent-gateway
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ../nginx/gateway/gateway.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
networks:
|
||||||
|
rent-prod:
|
||||||
|
external: true
|
||||||
|
rent-test:
|
||||||
|
external: true
|
||||||
@@ -3,17 +3,17 @@ version: '3.8'
|
|||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:8.0
|
image: mysql:8.0
|
||||||
container_name: rent-mysql
|
container_name: rent-prod-mysql
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-rent123456}
|
MYSQL_ROOT_PASSWORD: ${PROD_DB_PASSWORD:-rent123456}
|
||||||
MYSQL_DATABASE: rent_platform
|
MYSQL_DATABASE: rent_platform
|
||||||
MYSQL_CHARSET: utf8mb4
|
MYSQL_CHARSET: utf8mb4
|
||||||
MYSQL_COLLATION: utf8mb4_unicode_ci
|
MYSQL_COLLATION: utf8mb4_unicode_ci
|
||||||
ports:
|
ports:
|
||||||
- "3306:3306"
|
- "3306:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- mysql_data:/var/lib/mysql
|
- mysql_prod_data:/var/lib/mysql
|
||||||
- ../../database/migrations:/docker-entrypoint-initdb.d
|
- ../../database/migrations:/docker-entrypoint-initdb.d
|
||||||
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -21,27 +21,31 @@ services:
|
|||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
container_name: rent-redis
|
container_name: rent-prod-redis
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "6379:6379"
|
- "6379:6379"
|
||||||
volumes:
|
volumes:
|
||||||
- redis_data:/data
|
- redis_prod_data:/data
|
||||||
command: redis-server --appendonly yes
|
command: redis-server --appendonly yes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
server:
|
server:
|
||||||
build:
|
build:
|
||||||
context: ../..
|
context: ../..
|
||||||
dockerfile: deploy/docker/Dockerfile.server
|
dockerfile: deploy/docker/Dockerfile.server
|
||||||
container_name: rent-server
|
container_name: rent-prod-server
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
@@ -51,39 +55,60 @@ services:
|
|||||||
DB_HOST: mysql
|
DB_HOST: mysql
|
||||||
DB_PORT: 3306
|
DB_PORT: 3306
|
||||||
DB_USERNAME: root
|
DB_USERNAME: root
|
||||||
DB_PASSWORD: ${DB_PASSWORD:-rent123456}
|
DB_PASSWORD: ${PROD_DB_PASSWORD:-rent123456}
|
||||||
DB_DATABASE: rent_platform
|
DB_DATABASE: rent_platform
|
||||||
REDIS_HOST: redis
|
REDIS_HOST: redis
|
||||||
REDIS_PORT: 6379
|
REDIS_PORT: 6379
|
||||||
JWT_SECRET: ${JWT_SECRET:-change_this_in_production}
|
JWT_SECRET: ${PROD_JWT_SECRET:-change_this_in_production}
|
||||||
depends_on:
|
depends_on:
|
||||||
mysql:
|
mysql:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
merchant-admin:
|
merchant-admin:
|
||||||
build:
|
build:
|
||||||
context: ../..
|
context: ../..
|
||||||
dockerfile: deploy/docker/Dockerfile.merchant
|
dockerfile: deploy/docker/Dockerfile.merchant
|
||||||
container_name: rent-merchant-admin
|
container_name: rent-prod-merchant
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "8081:80"
|
- "8081:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
platform-admin:
|
platform-admin:
|
||||||
build:
|
build:
|
||||||
context: ../..
|
context: ../..
|
||||||
dockerfile: deploy/docker/Dockerfile.platform
|
dockerfile: deploy/docker/Dockerfile.platform
|
||||||
container_name: rent-platform-admin
|
container_name: rent-prod-platform
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "8082:80"
|
- "8082:80"
|
||||||
depends_on:
|
depends_on:
|
||||||
- server
|
- server
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
|
website:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile.website
|
||||||
|
container_name: rent-prod-website
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8083:80"
|
||||||
|
networks:
|
||||||
|
- rent-prod
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql_data:
|
mysql_prod_data:
|
||||||
redis_data:
|
redis_prod_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
rent-prod:
|
||||||
|
name: rent-prod
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: rent-test-mysql
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${TEST_DB_PASSWORD:-rent123456}
|
||||||
|
MYSQL_DATABASE: rent_platform
|
||||||
|
MYSQL_CHARSET: utf8mb4
|
||||||
|
MYSQL_COLLATION: utf8mb4_unicode_ci
|
||||||
|
ports:
|
||||||
|
- "3307:3306"
|
||||||
|
volumes:
|
||||||
|
- mysql_test_data:/var/lib/mysql
|
||||||
|
- ../../database/migrations:/docker-entrypoint-initdb.d
|
||||||
|
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: rent-test-redis
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "6380:6379"
|
||||||
|
volumes:
|
||||||
|
- redis_test_data:/data
|
||||||
|
command: redis-server --appendonly yes
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
server:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile.server
|
||||||
|
container_name: rent-test-server
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "3001:3000"
|
||||||
|
environment:
|
||||||
|
NODE_ENV: test
|
||||||
|
PORT: 3000
|
||||||
|
DB_HOST: mysql
|
||||||
|
DB_PORT: 3306
|
||||||
|
DB_USERNAME: root
|
||||||
|
DB_PASSWORD: ${TEST_DB_PASSWORD:-rent123456}
|
||||||
|
DB_DATABASE: rent_platform
|
||||||
|
REDIS_HOST: redis
|
||||||
|
REDIS_PORT: 6379
|
||||||
|
JWT_SECRET: ${TEST_JWT_SECRET:-change_this_in_test}
|
||||||
|
depends_on:
|
||||||
|
mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
merchant-admin:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile.merchant
|
||||||
|
container_name: rent-test-merchant
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "9081:80"
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
platform-admin:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile.platform
|
||||||
|
container_name: rent-test-platform
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "9082:80"
|
||||||
|
depends_on:
|
||||||
|
- server
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
website:
|
||||||
|
build:
|
||||||
|
context: ../..
|
||||||
|
dockerfile: deploy/docker/Dockerfile.website
|
||||||
|
container_name: rent-test-website
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "9083:80"
|
||||||
|
networks:
|
||||||
|
- rent-test
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql_test_data:
|
||||||
|
redis_test_data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
rent-test:
|
||||||
|
name: rent-test
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
worker_processes auto;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
error_log /var/log/nginx/error.log;
|
||||||
|
|
||||||
|
# Gzip
|
||||||
|
gzip on;
|
||||||
|
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
|
||||||
|
# 速率限制
|
||||||
|
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
|
||||||
|
|
||||||
|
# ===== 生产环境 Upstream =====
|
||||||
|
upstream prod_api {
|
||||||
|
server rent-prod-server:3000;
|
||||||
|
}
|
||||||
|
upstream prod_merchant {
|
||||||
|
server rent-prod-merchant:80;
|
||||||
|
}
|
||||||
|
upstream prod_platform {
|
||||||
|
server rent-prod-platform:80;
|
||||||
|
}
|
||||||
|
upstream prod_website {
|
||||||
|
server rent-prod-website:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===== 测试环境 Upstream =====
|
||||||
|
upstream test_api {
|
||||||
|
server rent-test-server:3000;
|
||||||
|
}
|
||||||
|
upstream test_merchant {
|
||||||
|
server rent-test-merchant:80;
|
||||||
|
}
|
||||||
|
upstream test_platform {
|
||||||
|
server rent-test-platform:80;
|
||||||
|
}
|
||||||
|
upstream test_website {
|
||||||
|
server rent-test-website:80;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===== 生产环境 =====
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name api.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
limit_req zone=api_limit burst=50 nodelay;
|
||||||
|
proxy_pass http://prod_api;
|
||||||
|
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;
|
||||||
|
client_max_body_size 50m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name www.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://prod_website;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name merchant.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://prod_merchant;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name platform-admin.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://prod_platform;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===== 测试环境 =====
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name api-test.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
limit_req zone=api_limit burst=50 nodelay;
|
||||||
|
proxy_pass http://test_api;
|
||||||
|
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;
|
||||||
|
client_max_body_size 50m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name test.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://test_website;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name merchant-test.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://test_merchant;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name platform-admin-test.pinzhuhui.com;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://test_platform;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 兜底:未知域名返回 444
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
return 444;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo " 品居会 - 服务器首次初始化"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ===== 1. 系统更新 =====
|
||||||
|
echo ">>> 更新系统包..."
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# ===== 2. 安装 Docker =====
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo ">>> 安装 Docker..."
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
echo "Docker 已安装。可能需要重新登录以生效。"
|
||||||
|
else
|
||||||
|
echo ">>> Docker 已安装,跳过。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===== 3. 验证 Docker Compose =====
|
||||||
|
if ! docker compose version &> /dev/null; then
|
||||||
|
echo ">>> 安装 Docker Compose 插件..."
|
||||||
|
sudo apt install -y docker-compose-plugin
|
||||||
|
else
|
||||||
|
echo ">>> Docker Compose 已安装,跳过。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===== 4. 安装 Git =====
|
||||||
|
if ! command -v git &> /dev/null; then
|
||||||
|
echo ">>> 安装 Git..."
|
||||||
|
sudo apt install -y git
|
||||||
|
else
|
||||||
|
echo ">>> Git 已安装,跳过。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===== 5. 安装 pnpm =====
|
||||||
|
if ! command -v pnpm &> /dev/null; then
|
||||||
|
echo ">>> 安装 pnpm..."
|
||||||
|
npm install -g pnpm 2>/dev/null || { echo "需要先安装 Node.js"; exit 1; }
|
||||||
|
else
|
||||||
|
echo ">>> pnpm 已安装,跳过。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===== 6. 配置环境变量 =====
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ENV_FILE="$PROJECT_DIR/deploy/docker/.env"
|
||||||
|
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo ">>> 创建 .env 文件..."
|
||||||
|
cp "$PROJECT_DIR/deploy/docker/.env.example" "$ENV_FILE"
|
||||||
|
echo ""
|
||||||
|
echo " *** 重要 ***"
|
||||||
|
echo " 请编辑 $ENV_FILE 填入真实密码和密钥。"
|
||||||
|
echo " 必填变量:"
|
||||||
|
echo " - PROD_DB_PASSWORD 生产环境数据库密码"
|
||||||
|
echo " - PROD_JWT_SECRET 生产环境 JWT 密钥"
|
||||||
|
echo " - TEST_DB_PASSWORD 测试环境数据库密码"
|
||||||
|
echo " - TEST_JWT_SECRET 测试环境 JWT 密钥"
|
||||||
|
echo ""
|
||||||
|
read -p " 按 Enter 打开编辑器,或 Ctrl+C 退出手动编辑..."
|
||||||
|
${EDITOR:-vi} "$ENV_FILE"
|
||||||
|
else
|
||||||
|
echo ">>> .env 文件已存在,跳过。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===== 7. 创建 Docker 网络 =====
|
||||||
|
echo ">>> 创建 Docker 网络..."
|
||||||
|
docker network create rent-prod 2>/dev/null || echo " rent-prod 网络已存在。"
|
||||||
|
docker network create rent-test 2>/dev/null || echo " rent-test 网络已存在。"
|
||||||
|
|
||||||
|
# ===== 8. 启动网关 =====
|
||||||
|
echo ">>> 启动 Gateway Nginx..."
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
docker compose -f deploy/docker/docker-compose.gateway.yml up -d
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo " 初始化完成!"
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
|
echo "后续步骤:"
|
||||||
|
echo " 1. 确认 .env 中的密码已正确填写"
|
||||||
|
echo " 2. 部署生产环境:make prod-deploy"
|
||||||
|
echo " 3. 部署测试环境:make test-deploy"
|
||||||
|
echo ""
|
||||||
|
echo " 配置以下 DNS 记录指向本服务器 IP:"
|
||||||
|
echo ""
|
||||||
|
echo " 生产环境:"
|
||||||
|
echo " api.pinzhuhui.com"
|
||||||
|
echo " www.pinzhuhui.com"
|
||||||
|
echo " merchant.pinzhuhui.com"
|
||||||
|
echo " platform-admin.pinzhuhui.com"
|
||||||
|
echo ""
|
||||||
|
echo " 测试环境:"
|
||||||
|
echo " api-test.pinzhuhui.com"
|
||||||
|
echo " test.pinzhuhui.com"
|
||||||
|
echo " merchant-test.pinzhuhui.com"
|
||||||
|
echo " platform-admin-test.pinzhuhui.com"
|
||||||
|
echo ""
|
||||||
|
echo " 4. (可选)配置 SSL 证书:"
|
||||||
|
echo " sudo apt install certbot"
|
||||||
|
echo " sudo certbot certonly --standalone -d api.pinzhuhui.com -d www.pinzhuhui.com ..."
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user