Files
mengyastore/生产环境部署.md

261 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 萌芽小店 · 生产环境部署指南
> 覆盖生产环境部署要点:后端目录为 **`mengyastore-backend-go`**,配置以 **环境变量** 为主(与本地 `.env` / `.env.production` 一致),无需再依赖 `config.json`。
---
## 目录
1. [环境要求](#1-环境要求)
2. [准备 MySQL](#2-准备-mysql)
3. [部署后端Docker](#3-部署后端docker)
4. [构建并部署前端](#4-构建并部署前端)
5. [Nginx 反向代理](#5-nginx-反向代理)
6. [验证部署](#6-验证部署)
7. [常见问题](#7-常见问题)
8. [升级与回滚](#8-升级与回滚)
---
## 1. 环境要求
| 组件 | 说明 |
|------|------|
| Linux 服务器 | Ubuntu 22.04 / Debian 12 等 |
| Docker 24+、Compose v2 | `docker compose version` |
| MySQL 8.x | 可内网独立实例 |
| Nginx 1.20+ | 静态资源 + `/api/` 反代 |
| Node.js 18+ | 仅前端 **构建** 时使用 |
可选:内网 **RabbitMQ**、**Redis**(与 `docker-compose` / 环境变量一致即可)。
---
## 2. 准备 MySQL
表结构由后端 **GORM AutoMigrate** 自动创建,只需 **建库 + 授权**
```sql
CREATE DATABASE IF NOT EXISTS `mengyastore`
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'mengyastore'@'%' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON `mengyastore`.* TO 'mengyastore'@'%';
FLUSH PRIVILEGES;
```
也可参考仓库内 `mengyastore-backend-go/init.sql`
---
## 3. 部署后端Docker
### 3.1 代码路径
```bash
git clone https://github.com/shumengya/mengyastore.git # 或你的仓库
cd mengyastore/mengyastore-backend-go
```
> 若历史文档写成 `mengyastore-backend`,请改为 **`mengyastore-backend-go`**。
### 3.2 配置方式(推荐)
生产 **不要** 把真实口令写进 Git。任选其一
- **A.** 在宿主机导出环境变量后执行 `docker compose up`Compose 中 `${VAR:-默认值}` 会读取宿主机环境)。
- **B.** 在服务器的 `mengyastore-backend-go/` 放置 **`.env`**(勿提交),并在 `docker-compose.yml` 中增加 `env_file: .env`(若你自行加上该条目);当前仓库默认 compose **未挂载** `.env`,请通过 **environment****export** 注入。
**必填 / 常用变量(与 `internal/config/config.go` 一致):**
| 变量 | 说明 |
|------|------|
| `APP_ENV` | `production` |
| `DATABASE_DSN` | 生产 MySQL 连接串 |
| `ADMIN_TOKEN` | 管理后台令牌(强随机) |
| `AUTH_API_URL` | SproutGate 认证网关 Base URL |
| `RABBITMQ_ENABLED` | `true` / `false` |
| `RABBITMQ_URL` | 启用 MQ 时完整 `amqp://…`(或用各 `RABBITMQ_*` 拼装,见配置注释) |
| `REDIS_ENABLED` | `true` / `false` |
| `REDIS_ADDR``REDIS_PASSWORD``REDIS_DB` | 启用 Redis 探测/缓存时 |
| `HTTP_LISTEN_ADDR` | 可选,默认容器内 `:8080` |
| `PUBLIC_API_BASE_URL` | 可选,管理端「系统状态」展示的对外 API 基址(反代 HTTPS 时建议设) |
根据业务关闭不需要的中间件时,将 `RABBITMQ_ENABLED``REDIS_ENABLED` 设为 `false`,避免无实例仍去连接。
### 3.3 修改 `docker-compose.yml`
部署前请 **核对并本地化**
- `DATABASE_DSN` 指向你的库。
- `ports`(示例 `28081:8080`)是否与 Nginx `proxy_pass` 一致。
- **删除或替换** 仓库中带默认口令的示例值;通过宿主机环境注入生产密钥。
示例(**仅结构示意,口令用环境变量**
```yaml
services:
backend:
build: { context: . }
container_name: mengyastore-backend
ports:
- "28081:8080"
environment:
APP_ENV: production
GIN_MODE: release
TZ: Asia/Shanghai
DATABASE_DSN: ${DATABASE_DSN}
ADMIN_TOKEN: ${ADMIN_TOKEN}
AUTH_API_URL: ${AUTH_API_URL:-}
REDIS_ENABLED: ${REDIS_ENABLED:-false}
REDIS_ADDR: ${REDIS_ADDR:-}
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
RABBITMQ_ENABLED: ${RABBITMQ_ENABLED:-false}
RABBITMQ_ENV: prod
RABBITMQ_URL: ${RABBITMQ_URL:-}
restart: unless-stopped
```
### 3.4 启动
```bash
cd /opt/mengyastore/mengyastore-backend-go # 你的实际路径
export DATABASE_DSN='...'
export ADMIN_TOKEN='...'
# … 其他变量按需 export
docker compose up -d --build
docker compose logs -f
```
预期日志含:`[DB] 数据库连接成功,表结构已同步``萌芽小店后端启动于 http://localhost:8080`
### 3.5 健康检查
```bash
curl -s http://127.0.0.1:28081/api/health
curl -s http://127.0.0.1:28081/api/products
```
---
## 4. 构建并部署前端
```bash
cd mengyastore-frontend
npm ci || npm install
```
**同源部署**Nginx 把 `/api/` 反代到后端):构建前可不设 `VITE_API_BASE_URL`,打包后请求会走当前站点域名。
**前后端不同域**:创建 `.env.production`
```env
VITE_API_BASE_URL=https://你的-api-域名
```
```bash
npm run build
```
`dist/` 同步到服务器,例如 `/var/www/mengyastore/`
```bash
rsync -avz --delete dist/ user@server:/var/www/mengyastore/
```
---
## 5. Nginx 反向代理
```nginx
server {
listen 80;
server_name your-domain.com;
root /var/www/mengyastore;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:28081;
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;
proxy_connect_timeout 30s;
proxy_read_timeout 60s;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|webmanifest)$ {
expires 7d;
add_header Cache-Control "public, immutable";
}
}
```
HTTPS 可使用 `certbot --nginx` 签发 Let's Encrypt。
---
## 6. 验证部署
- [ ] 首页与商品列表正常。
- [ ] SproutGate 登录后收藏、聊天、我的订单可用。
- [ ] **Logo 连点 5 次** → 管理员验证 → 带 `?token=` 或使用 `X-Admin-Token` 访问后台。
- [ ] 后台 **系统状态**MySQL / Redis / RabbitMQ若启用显示合理。
- [ ] 商品:**卡密** 与 **固定内容** 两种类型可分别保存;固定内容商品前台库存显示「不限」。
- [ ] 下一单:结算页金额、收款码区、**复制订单号**、确认后内容与邮件/MQ 预期一致(依你的 SMTP/MQ 配置)。
- [ ] PWA 可安装(如需要)。
---
## 7. 常见问题
**CORS / 白屏**
确认 Nginx `location /api/` 指向后端端口,且容器 `docker compose ps` 为运行中。
**管理 Token 无效**
核对容器内实际生效的 `ADMIN_TOKEN`(与前端输入一致)。当前项目 **不再依赖** `config.json`
**RabbitMQ 报 504 / channel closed**
服务端已实现重连与消费重启;若仍异常,查 Broker 日志、网络与 `RABBITMQ_URL`/vhost/权限。
**数据库连不上**
在宿主机用 `mysql` 客户端测 `DATABASE_DSN` 同款主机端口账号Docker 网络须能访问 MySQL。
**站点设置 KV 查询**
后端对缺失的 `site_settings` 键使用不产生「record not found」噪声的查询方式首次保存 SMTP 等后会写入库表。
---
## 8. 升级与回滚
```bash
cd mengyastore-backend-go
git pull
docker compose up -d --build
docker compose logs -f --tail=100
```
回滚:保留上一版本的镜像 tag 或 git tag重新 `docker compose up` 指定旧镜像(视你实际镜像命名而定)。
---
## 附:目录结构示例
```
/opt/mengyastore/
mengyastore-backend-go/
docker-compose.yml
Dockerfile
.env ← 仅存服务器本地,勿提交 Git
...
/var/www/mengyastore/ ← 前端 dist
index.html
assets/
```
部署完成后访问你的域名即可。