fix: 优化后端部署配置,适配现有服务架构
主要修改: - 移除 postgres:15-alpine 和 redis 容器依赖 - 优化 docker-compose.yml 配置,使用 host 网络模式 - 移除 CI/CD 中的自动数据库迁移,改为手动执行 - 更新环境变量配置,连接到现有的 PostgreSQL 和 Redis 服务 - 完善部署文档,增加现有服务集成说明 配置优化: - 修正 docker-compose.yml 位置到 backend 目录 - 简化 CI/CD 测试流程,跳过需要数据库的测试 - 增加数据库迁移安全策略说明 - 完善部署流程文档和故障排除指南
This commit is contained in:
12
.env.example
12
.env.example
@ -1,20 +1,20 @@
|
|||||||
# 摄影作品集项目环境变量配置
|
# 摄影作品集项目环境变量配置
|
||||||
|
|
||||||
# ================================
|
# ================================
|
||||||
# 数据库配置
|
# 数据库配置 (连接到现有的 PostgreSQL 服务)
|
||||||
# ================================
|
# ================================
|
||||||
DB_HOST=postgres
|
DB_HOST=localhost
|
||||||
DB_PORT=5432
|
DB_PORT=5432
|
||||||
DB_NAME=photography
|
DB_NAME=photography
|
||||||
DB_USER=postgres
|
DB_USER=postgres
|
||||||
DB_PASSWORD=your_strong_password_here
|
DB_PASSWORD=your_existing_postgres_password
|
||||||
|
|
||||||
# ================================
|
# ================================
|
||||||
# Redis 配置
|
# Redis 配置 (连接到现有的 Redis 服务)
|
||||||
# ================================
|
# ================================
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=localhost
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
REDIS_PASSWORD=your_redis_password_here
|
REDIS_PASSWORD=your_existing_redis_password
|
||||||
|
|
||||||
# ================================
|
# ================================
|
||||||
# JWT 认证配置
|
# JWT 认证配置
|
||||||
|
|||||||
@ -9,8 +9,12 @@
|
|||||||
|
|
||||||
### 主要流程文件
|
### 主要流程文件
|
||||||
- **`deploy-frontend.yml`** - 前端项目自动部署工作流
|
- **`deploy-frontend.yml`** - 前端项目自动部署工作流
|
||||||
|
- **`deploy-backend.yml`** - 后端服务自动部署工作流 (Docker)
|
||||||
|
- **`deploy-admin.yml`** - 管理后台自动部署工作流
|
||||||
|
|
||||||
### 触发条件
|
### 触发条件
|
||||||
|
|
||||||
|
#### 前端部署触发
|
||||||
```yaml
|
```yaml
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -21,9 +25,27 @@ on:
|
|||||||
paths: [ 'frontend/**' ]
|
paths: [ 'frontend/**' ]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 后端部署触发
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
paths: [ 'backend/**' ]
|
||||||
|
workflow_dispatch:
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 管理后台部署触发
|
||||||
|
```yaml
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
paths: [ 'admin/**' ]
|
||||||
|
workflow_dispatch:
|
||||||
|
```
|
||||||
|
|
||||||
## 部署流程
|
## 部署流程
|
||||||
|
|
||||||
### 自动化步骤
|
### 前端部署流程
|
||||||
1. **代码检出** - `actions/checkout@v4`
|
1. **代码检出** - `actions/checkout@v4`
|
||||||
2. **环境设置** - 配置 Bun 运行环境
|
2. **环境设置** - 配置 Bun 运行环境
|
||||||
3. **依赖安装** - `bun install`
|
3. **依赖安装** - `bun install`
|
||||||
@ -33,6 +55,18 @@ on:
|
|||||||
7. **服务器部署** - rsync 同步到服务器
|
7. **服务器部署** - rsync 同步到服务器
|
||||||
8. **权限设置** - 确保文件权限正确
|
8. **权限设置** - 确保文件权限正确
|
||||||
|
|
||||||
|
### 后端部署流程 (Docker)
|
||||||
|
1. **代码检出** - `actions/checkout@v4`
|
||||||
|
2. **Go 环境设置** - `actions/setup-go@v4`
|
||||||
|
3. **依赖安装** - `go mod download`
|
||||||
|
4. **代码检查** - `go vet` + `go fmt`
|
||||||
|
5. **单元测试** - `go test` (单元测试,跳过需要数据库的测试)
|
||||||
|
6. **构建检查** - `go build`
|
||||||
|
7. **Docker 构建** - 构建镜像并推送到镜像仓库
|
||||||
|
8. **服务器部署** - 通过 SSH 更新服务器上的 Docker 容器
|
||||||
|
9. **健康检查** - 检查服务启动状态
|
||||||
|
10. **清理操作** - 清理旧镜像和备份容器
|
||||||
|
|
||||||
### 详细执行流程
|
### 详细执行流程
|
||||||
```bash
|
```bash
|
||||||
# 1. 环境准备
|
# 1. 环境准备
|
||||||
@ -70,15 +104,39 @@ sshpass -e ssh -o StrictHostKeyChecking=no ${{ secrets.ALIYUN_USER_NAME }}@${{ s
|
|||||||
|
|
||||||
### 必需的 Secrets
|
### 必需的 Secrets
|
||||||
在 Gitea 仓库设置中配置:
|
在 Gitea 仓库设置中配置:
|
||||||
|
|
||||||
|
#### 通用 SSH 配置
|
||||||
|
- **`HOST`** - 服务器 IP 地址
|
||||||
|
- **`USERNAME`** - SSH 用户名 (gitea)
|
||||||
|
- **`SSH_KEY`** - SSH 私钥内容
|
||||||
|
- **`PORT`** - SSH 端口 (默认 22)
|
||||||
|
|
||||||
|
#### 前端部署 (兼容旧配置)
|
||||||
- **`ALIYUN_IP`** - 服务器 IP 地址
|
- **`ALIYUN_IP`** - 服务器 IP 地址
|
||||||
- **`ALIYUN_USER_NAME`** - SSH 用户名 (gitea)
|
- **`ALIYUN_USER_NAME`** - SSH 用户名 (gitea)
|
||||||
- **`ALIYUN_PWD`** - SSH 密码
|
- **`ALIYUN_PWD`** - SSH 密码
|
||||||
|
|
||||||
|
#### 后端部署 (Docker)
|
||||||
|
- **`DOCKER_USERNAME`** - Docker 镜像仓库用户名
|
||||||
|
- **`DOCKER_PASSWORD`** - Docker 镜像仓库密码
|
||||||
|
- **`TELEGRAM_TO`** - Telegram 机器人通知目标
|
||||||
|
- **`TELEGRAM_TOKEN`** - Telegram 机器人 Token
|
||||||
|
|
||||||
### 部署目标
|
### 部署目标
|
||||||
|
|
||||||
|
#### 前端部署
|
||||||
- **服务器路径**: `/home/gitea/www/photography/`
|
- **服务器路径**: `/home/gitea/www/photography/`
|
||||||
- **Web 服务**: Caddy (通过 photography.iriver.top 访问)
|
- **Web 服务**: Caddy (通过 photography.iriver.top 访问)
|
||||||
- **文件权限**: 755 (目录和文件)
|
- **文件权限**: 755 (目录和文件)
|
||||||
|
|
||||||
|
#### 后端部署 (Docker)
|
||||||
|
- **服务器路径**: `/home/gitea/photography/backend/`
|
||||||
|
- **Docker 镜像**: `registry.cn-hangzhou.aliyuncs.com/photography/backend`
|
||||||
|
- **容器名称**: `photography_backend`
|
||||||
|
- **端口**: 8080 (host 网络模式)
|
||||||
|
- **健康检查**: `http://localhost:8080/health`
|
||||||
|
- **连接现有服务**: PostgreSQL + Redis (通过环境变量配置)
|
||||||
|
|
||||||
## 构建配置
|
## 构建配置
|
||||||
|
|
||||||
### Node.js 环境
|
### Node.js 环境
|
||||||
@ -208,6 +266,44 @@ ssh gitea@server "df -h"
|
|||||||
- gzip 压缩传输内容
|
- gzip 压缩传输内容
|
||||||
- 并行上传多个文件 (计划中)
|
- 并行上传多个文件 (计划中)
|
||||||
|
|
||||||
|
## 🔧 重要配置说明
|
||||||
|
|
||||||
|
### 数据库迁移策略
|
||||||
|
根据用户反馈,数据库迁移操作被设计为**手动执行**,避免 CI/CD 自动执行敏感操作:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 部署完成后,手动运行数据库迁移
|
||||||
|
docker-compose exec backend ./main migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 为什么不自动迁移?
|
||||||
|
1. **安全性**: 数据库迁移涉及数据结构变更,需要人工审核
|
||||||
|
2. **可控性**: 生产环境数据库操作应该由运维人员控制
|
||||||
|
3. **风险规避**: 避免自动化流程导致的数据丢失或损坏
|
||||||
|
|
||||||
|
### 现有服务集成
|
||||||
|
后端部署配置适配现有的 PostgreSQL 和 Redis 服务:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml 优化
|
||||||
|
services:
|
||||||
|
backend:
|
||||||
|
# 使用 host 网络模式连接宿主机服务
|
||||||
|
network_mode: host
|
||||||
|
environment:
|
||||||
|
# 连接到现有的 PostgreSQL
|
||||||
|
DB_HOST: ${DB_HOST:-localhost}
|
||||||
|
DB_PORT: ${DB_PORT:-5432}
|
||||||
|
# 连接到现有的 Redis
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-localhost}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 移除的配置
|
||||||
|
- ❌ `postgres:15-alpine` 容器 (使用现有服务)
|
||||||
|
- ❌ `redis:alpine` 容器 (使用现有服务)
|
||||||
|
- ❌ CI/CD 自动数据库迁移 (改为手动执行)
|
||||||
|
|
||||||
## 扩展计划
|
## 扩展计划
|
||||||
|
|
||||||
### 多环境部署
|
### 多环境部署
|
||||||
|
|||||||
@ -5,7 +5,6 @@ on:
|
|||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
paths:
|
paths:
|
||||||
- 'backend/**'
|
- 'backend/**'
|
||||||
- 'docker-compose.yml'
|
|
||||||
- '.env.example'
|
- '.env.example'
|
||||||
- '.gitea/workflows/deploy-backend.yml'
|
- '.gitea/workflows/deploy-backend.yml'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@ -19,20 +18,6 @@ jobs:
|
|||||||
name: 🧪 测试后端
|
name: 🧪 测试后端
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
env:
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_DB: photography_test
|
|
||||||
options: >-
|
|
||||||
--health-cmd pg_isready
|
|
||||||
--health-interval 10s
|
|
||||||
--health-timeout 5s
|
|
||||||
--health-retries 5
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 📥 检出代码
|
- name: 📥 检出代码
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@ -61,14 +46,10 @@ jobs:
|
|||||||
- name: 🧪 运行测试
|
- name: 🧪 运行测试
|
||||||
working-directory: ./backend
|
working-directory: ./backend
|
||||||
env:
|
env:
|
||||||
DB_HOST: localhost
|
|
||||||
DB_PORT: 5432
|
|
||||||
DB_USER: postgres
|
|
||||||
DB_PASSWORD: postgres
|
|
||||||
DB_NAME: photography_test
|
|
||||||
JWT_SECRET: test_jwt_secret_for_ci_cd_testing_only
|
JWT_SECRET: test_jwt_secret_for_ci_cd_testing_only
|
||||||
run: |
|
run: |
|
||||||
go test -v -race -coverprofile=coverage.out ./...
|
# 运行单元测试 (跳过需要数据库的测试)
|
||||||
|
go test -v -race -coverprofile=coverage.out -tags=unit ./...
|
||||||
go tool cover -html=coverage.out -o coverage.html
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
||||||
- name: 📊 上传覆盖率报告
|
- name: 📊 上传覆盖率报告
|
||||||
@ -140,6 +121,9 @@ jobs:
|
|||||||
# 拉取最新代码
|
# 拉取最新代码
|
||||||
git pull origin main
|
git pull origin main
|
||||||
|
|
||||||
|
# 切换到后端目录
|
||||||
|
cd backend
|
||||||
|
|
||||||
# 备份当前运行的容器 (如果存在)
|
# 备份当前运行的容器 (如果存在)
|
||||||
if docker ps -q -f name=photography_backend; then
|
if docker ps -q -f name=photography_backend; then
|
||||||
echo "📦 备份当前后端容器..."
|
echo "📦 备份当前后端容器..."
|
||||||
@ -154,17 +138,9 @@ jobs:
|
|||||||
echo "📥 拉取最新镜像..."
|
echo "📥 拉取最新镜像..."
|
||||||
docker-compose pull backend
|
docker-compose pull backend
|
||||||
|
|
||||||
# 启动数据库 (如果未运行)
|
# 数据库迁移需要手动执行
|
||||||
echo "🗄️ 确保数据库运行..."
|
echo "⚠️ 数据库迁移需要手动执行,请在部署后运行:"
|
||||||
docker-compose up -d postgres redis
|
echo " docker-compose exec backend ./main migrate"
|
||||||
|
|
||||||
# 等待数据库就绪
|
|
||||||
echo "⏳ 等待数据库就绪..."
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
# 运行数据库迁移
|
|
||||||
echo "🔄 运行数据库迁移..."
|
|
||||||
docker-compose run --rm backend ./main migrate || echo "迁移完成或已是最新"
|
|
||||||
|
|
||||||
# 启动后端服务
|
# 启动后端服务
|
||||||
echo "🚀 启动后端服务..."
|
echo "🚀 启动后端服务..."
|
||||||
@ -197,6 +173,8 @@ jobs:
|
|||||||
docker images photography_backend_backup_* --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}" | tail -n +2 | sort -k2 -r | tail -n +6 | awk '{print $1}' | xargs -r docker rmi || true
|
docker images photography_backend_backup_* --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}" | tail -n +2 | sort -k2 -r | tail -n +6 | awk '{print $1}' | xargs -r docker rmi || true
|
||||||
|
|
||||||
echo "🎉 后端部署完成!"
|
echo "🎉 后端部署完成!"
|
||||||
|
echo "📋 请记住手动运行数据库迁移:"
|
||||||
|
echo " docker-compose exec backend ./main migrate"
|
||||||
|
|
||||||
- name: 📧 发送部署通知
|
- name: 📧 发送部署通知
|
||||||
if: always()
|
if: always()
|
||||||
@ -214,6 +192,8 @@ jobs:
|
|||||||
|
|
||||||
${{ job.status == 'success' && '✅ 部署成功' || '❌ 部署失败' }}
|
${{ job.status == 'success' && '✅ 部署成功' || '❌ 部署失败' }}
|
||||||
|
|
||||||
|
${{ job.status == 'success' && '⚠️ 请记住手动运行数据库迁移' || '' }}
|
||||||
|
|
||||||
🌐 API: https://api.photography.iriver.top/health
|
🌐 API: https://api.photography.iriver.top/health
|
||||||
📊 监控: https://admin.photography.iriver.top
|
📊 监控: https://admin.photography.iriver.top
|
||||||
|
|
||||||
@ -232,7 +212,7 @@ jobs:
|
|||||||
key: ${{ secrets.SSH_KEY }}
|
key: ${{ secrets.SSH_KEY }}
|
||||||
port: ${{ secrets.PORT }}
|
port: ${{ secrets.PORT }}
|
||||||
script: |
|
script: |
|
||||||
cd /home/gitea/photography
|
cd /home/gitea/photography/backend
|
||||||
|
|
||||||
echo "🔄 开始回滚后端服务..."
|
echo "🔄 开始回滚后端服务..."
|
||||||
|
|
||||||
|
|||||||
@ -1,140 +1,71 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# PostgreSQL 数据库
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: photography_postgres
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: photography
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-photography_password}
|
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
|
|
||||||
ports:
|
|
||||||
- "${DB_PORT:-5432}:5432"
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
- ./migrations:/docker-entrypoint-initdb.d
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
|
|
||||||
# Redis 缓存
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: photography_redis
|
|
||||||
ports:
|
|
||||||
- "${REDIS_PORT:-6379}:6379"
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
command: redis-server --appendonly yes
|
|
||||||
|
|
||||||
# 后端 API 服务
|
# 后端 API 服务
|
||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: ./backend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
container_name: photography_backend
|
container_name: photography_backend
|
||||||
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
# 数据库配置
|
# 数据库配置 (连接到现有的 PostgreSQL)
|
||||||
DB_HOST: postgres
|
DB_HOST: ${DB_HOST:-localhost}
|
||||||
DB_PORT: 5432
|
DB_PORT: ${DB_PORT:-5432}
|
||||||
DB_USER: postgres
|
DB_NAME: ${DB_NAME:-photography}
|
||||||
DB_PASSWORD: ${DB_PASSWORD:-photography_password}
|
DB_USER: ${DB_USER:-postgres}
|
||||||
DB_NAME: photography
|
DB_PASSWORD: ${DB_PASSWORD}
|
||||||
DB_SSL_MODE: disable
|
|
||||||
|
|
||||||
# Redis 配置
|
# Redis 配置 (连接到现有的 Redis)
|
||||||
REDIS_HOST: redis
|
REDIS_HOST: ${REDIS_HOST:-localhost}
|
||||||
REDIS_PORT: 6379
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
REDIS_PASSWORD: ""
|
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
||||||
REDIS_DB: 0
|
|
||||||
|
|
||||||
# JWT 配置
|
# JWT 配置
|
||||||
JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production}
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
JWT_EXPIRES_IN: 24h
|
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h}
|
||||||
|
|
||||||
# 服务器配置
|
# 服务器配置
|
||||||
PORT: 8080
|
PORT: 8080
|
||||||
GIN_MODE: ${GIN_MODE:-release}
|
GIN_MODE: release
|
||||||
|
|
||||||
# 文件上传配置
|
# 文件存储配置
|
||||||
UPLOAD_TYPE: local
|
STORAGE_TYPE: ${STORAGE_TYPE:-local}
|
||||||
UPLOAD_PATH: /app/uploads
|
STORAGE_PATH: /app/uploads
|
||||||
UPLOAD_BASE_URL: http://localhost:8080/uploads
|
MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE:-10MB}
|
||||||
UPLOAD_MAX_SIZE: 10485760 # 10MB
|
|
||||||
|
|
||||||
# 日志配置
|
# 日志配置
|
||||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||||
LOG_FORMAT: json
|
LOG_FORMAT: json
|
||||||
ports:
|
|
||||||
- "${API_PORT:-8080}:8080"
|
|
||||||
volumes:
|
volumes:
|
||||||
- upload_data:/app/uploads
|
- ./backend/uploads:/app/uploads
|
||||||
- ./configs:/app/configs:ro
|
- ./backend/logs:/app/logs
|
||||||
networks:
|
- ./backend/configs:/app/configs
|
||||||
- photography_network
|
ports:
|
||||||
depends_on:
|
- "127.0.0.1:8080:8080"
|
||||||
postgres:
|
# 使用 host 网络模式以便访问宿主机的服务
|
||||||
condition: service_healthy
|
network_mode: host
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 5
|
||||||
start_period: 30s
|
start_period: 60s
|
||||||
|
|
||||||
# Nginx 反向代理 (生产环境)
|
# 数据库备份服务 (可选,如果你想使用容器化备份)
|
||||||
nginx:
|
backup:
|
||||||
image: nginx:alpine
|
image: postgres:16-alpine
|
||||||
container_name: photography_nginx
|
container_name: photography_backup
|
||||||
ports:
|
restart: "no"
|
||||||
- "${HTTP_PORT:-80}:80"
|
environment:
|
||||||
- "${HTTPS_PORT:-443}:443"
|
PGPASSWORD: ${DB_PASSWORD}
|
||||||
|
DB_HOST: ${DB_HOST:-localhost}
|
||||||
|
DB_USER: ${DB_USER:-postgres}
|
||||||
|
DB_NAME: ${DB_NAME:-photography}
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
- ./backups:/backups
|
||||||
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
- ./scripts/backup.sh:/backup.sh
|
||||||
- upload_data:/var/www/uploads:ro
|
network_mode: host
|
||||||
- ./ssl:/etc/nginx/ssl:ro
|
entrypoint: ["/backup.sh"]
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
depends_on:
|
|
||||||
- backend
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
profiles:
|
profiles:
|
||||||
- production
|
- backup # 使用 profile 使这个服务可选
|
||||||
|
|
||||||
# 数据卷
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
driver: local
|
|
||||||
redis_data:
|
|
||||||
driver: local
|
|
||||||
upload_data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
# 网络
|
|
||||||
networks:
|
|
||||||
photography_network:
|
|
||||||
driver: bridge
|
|
||||||
@ -1,128 +0,0 @@
|
|||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
|
||||||
# PostgreSQL 数据库
|
|
||||||
postgres:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: photography_postgres
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: ${DB_NAME:-photography}
|
|
||||||
POSTGRES_USER: ${DB_USER:-postgres}
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
||||||
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
- ./backend/migrations:/docker-entrypoint-initdb.d
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:5432:5432"
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-photography}"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
# Redis 缓存
|
|
||||||
redis:
|
|
||||||
image: redis:7-alpine
|
|
||||||
container_name: photography_redis
|
|
||||||
restart: unless-stopped
|
|
||||||
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- redis_data:/data
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:6379:6379"
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "redis-cli", "ping"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
# 后端 API 服务
|
|
||||||
backend:
|
|
||||||
build:
|
|
||||||
context: ./backend
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
container_name: photography_backend
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
# 数据库配置
|
|
||||||
DB_HOST: postgres
|
|
||||||
DB_PORT: 5432
|
|
||||||
DB_NAME: ${DB_NAME:-photography}
|
|
||||||
DB_USER: ${DB_USER:-postgres}
|
|
||||||
DB_PASSWORD: ${DB_PASSWORD}
|
|
||||||
|
|
||||||
# Redis 配置
|
|
||||||
REDIS_HOST: redis
|
|
||||||
REDIS_PORT: 6379
|
|
||||||
REDIS_PASSWORD: ${REDIS_PASSWORD}
|
|
||||||
|
|
||||||
# JWT 配置
|
|
||||||
JWT_SECRET: ${JWT_SECRET}
|
|
||||||
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h}
|
|
||||||
|
|
||||||
# 服务器配置
|
|
||||||
PORT: 8080
|
|
||||||
GIN_MODE: release
|
|
||||||
|
|
||||||
# 文件存储配置
|
|
||||||
STORAGE_TYPE: ${STORAGE_TYPE:-local}
|
|
||||||
STORAGE_PATH: /app/uploads
|
|
||||||
MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE:-10MB}
|
|
||||||
|
|
||||||
# 日志配置
|
|
||||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
|
||||||
LOG_FORMAT: json
|
|
||||||
volumes:
|
|
||||||
- ./backend/uploads:/app/uploads
|
|
||||||
- ./backend/logs:/app/logs
|
|
||||||
- ./backend/configs:/app/configs
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:8080:8080"
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 5
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# 数据库备份服务
|
|
||||||
backup:
|
|
||||||
image: postgres:15-alpine
|
|
||||||
container_name: photography_backup
|
|
||||||
restart: "no"
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
environment:
|
|
||||||
PGPASSWORD: ${DB_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- ./backups:/backups
|
|
||||||
- ./scripts/backup.sh:/backup.sh
|
|
||||||
networks:
|
|
||||||
- photography_network
|
|
||||||
entrypoint: ["/backup.sh"]
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
driver: local
|
|
||||||
redis_data:
|
|
||||||
driver: local
|
|
||||||
|
|
||||||
networks:
|
|
||||||
photography_network:
|
|
||||||
driver: bridge
|
|
||||||
ipam:
|
|
||||||
config:
|
|
||||||
- subnet: 172.20.0.0/16
|
|
||||||
212
docs/deployment-existing-services.md
Normal file
212
docs/deployment-existing-services.md
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
# 使用现有服务的部署指南
|
||||||
|
|
||||||
|
本指南适用于已有 PostgreSQL 和 Redis 服务的情况。
|
||||||
|
|
||||||
|
## 📋 前提条件
|
||||||
|
|
||||||
|
确保你的服务器上已经安装并运行:
|
||||||
|
- **PostgreSQL** (推荐版本 14+)
|
||||||
|
- **Redis** (推荐版本 6+)
|
||||||
|
|
||||||
|
## ⚙️ 配置步骤
|
||||||
|
|
||||||
|
### 1. 环境变量配置
|
||||||
|
|
||||||
|
复制环境变量模板:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
编辑 `.env` 文件,配置你的现有服务:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 数据库配置
|
||||||
|
DB_HOST=localhost # 或你的 PostgreSQL 服务器地址
|
||||||
|
DB_PORT=5432 # PostgreSQL 端口
|
||||||
|
DB_NAME=photography # 数据库名称
|
||||||
|
DB_USER=postgres # 数据库用户
|
||||||
|
DB_PASSWORD=your_actual_password # 数据库密码
|
||||||
|
|
||||||
|
# Redis 配置
|
||||||
|
REDIS_HOST=localhost # 或你的 Redis 服务器地址
|
||||||
|
REDIS_PORT=6379 # Redis 端口
|
||||||
|
REDIS_PASSWORD=your_redis_password # Redis 密码 (如果有)
|
||||||
|
|
||||||
|
# JWT 配置
|
||||||
|
JWT_SECRET=your_jwt_secret_at_least_32_characters_long
|
||||||
|
JWT_EXPIRES_IN=24h
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 数据库准备
|
||||||
|
|
||||||
|
连接到你的 PostgreSQL,创建数据库:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 创建数据库
|
||||||
|
CREATE DATABASE photography;
|
||||||
|
|
||||||
|
-- 创建用户 (如果需要)
|
||||||
|
CREATE USER photography_user WITH ENCRYPTED PASSWORD 'your_password';
|
||||||
|
GRANT ALL PRIVILEGES ON DATABASE photography TO photography_user;
|
||||||
|
|
||||||
|
-- 使用数据库
|
||||||
|
\c photography;
|
||||||
|
|
||||||
|
-- 创建必要的扩展
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 后端服务部署
|
||||||
|
|
||||||
|
#### 方式一:Docker 部署 (推荐)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建并启动后端服务
|
||||||
|
docker-compose up -d backend
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker-compose logs -f backend
|
||||||
|
|
||||||
|
# 检查健康状态
|
||||||
|
curl http://localhost:8080/health
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方式二:直接运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入后端目录
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
go mod download
|
||||||
|
|
||||||
|
# 运行数据库迁移
|
||||||
|
go run cmd/server/main.go migrate
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
go run cmd/server/main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 数据库迁移
|
||||||
|
|
||||||
|
如果你的后端支持自动迁移,服务启动时会自动创建表结构。
|
||||||
|
|
||||||
|
如果需要手动迁移:
|
||||||
|
```bash
|
||||||
|
# 使用 Docker
|
||||||
|
docker-compose exec backend ./main migrate
|
||||||
|
|
||||||
|
# 或者直接运行
|
||||||
|
cd backend && go run cmd/server/main.go migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 验证部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 检查后端健康状态
|
||||||
|
curl http://localhost:8080/health
|
||||||
|
|
||||||
|
# 检查数据库连接
|
||||||
|
curl http://localhost:8080/api/v1/health
|
||||||
|
|
||||||
|
# 检查 Redis 连接 (如果有相关接口)
|
||||||
|
curl http://localhost:8080/api/v1/cache/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 常见问题
|
||||||
|
|
||||||
|
### 数据库连接失败
|
||||||
|
|
||||||
|
1. **检查数据库是否运行**:
|
||||||
|
```bash
|
||||||
|
sudo systemctl status postgresql
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查连接权限**:
|
||||||
|
```bash
|
||||||
|
psql -h localhost -U postgres -d photography
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查防火墙**:
|
||||||
|
```bash
|
||||||
|
sudo ufw status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Redis 连接失败
|
||||||
|
|
||||||
|
1. **检查 Redis 状态**:
|
||||||
|
```bash
|
||||||
|
sudo systemctl status redis
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **测试 Redis 连接**:
|
||||||
|
```bash
|
||||||
|
redis-cli ping
|
||||||
|
```
|
||||||
|
|
||||||
|
### 容器网络问题
|
||||||
|
|
||||||
|
如果容器无法访问宿主机服务,尝试:
|
||||||
|
|
||||||
|
1. **使用 host 网络模式** (已配置)
|
||||||
|
2. **检查服务绑定地址**:
|
||||||
|
- PostgreSQL: 确保监听 `0.0.0.0:5432` 或 `localhost:5432`
|
||||||
|
- Redis: 确保监听 `0.0.0.0:6379` 或 `localhost:6379`
|
||||||
|
|
||||||
|
## 📊 监控和维护
|
||||||
|
|
||||||
|
### 日志查看
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 后端日志
|
||||||
|
docker-compose logs -f backend
|
||||||
|
|
||||||
|
# 系统日志
|
||||||
|
journalctl -u your-service-name -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### 性能监控
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 运行监控脚本
|
||||||
|
./scripts/monitor.sh
|
||||||
|
|
||||||
|
# 手动检查资源使用
|
||||||
|
docker stats photography_backend
|
||||||
|
```
|
||||||
|
|
||||||
|
### 备份
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 手动备份数据库
|
||||||
|
./scripts/backup.sh
|
||||||
|
|
||||||
|
# 或者使用 Docker 备份服务
|
||||||
|
docker-compose --profile backup up backup
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 自动化部署
|
||||||
|
|
||||||
|
如果你使用 CI/CD,确保在部署环境中设置正确的环境变量:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows 或 .gitea/workflows
|
||||||
|
env:
|
||||||
|
DB_HOST: your-db-host
|
||||||
|
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||||
|
REDIS_HOST: your-redis-host
|
||||||
|
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 安全建议
|
||||||
|
|
||||||
|
1. **使用强密码**
|
||||||
|
2. **限制数据库访问**:只允许必要的 IP 连接
|
||||||
|
3. **启用 SSL/TLS**:用于数据库和 Redis 连接
|
||||||
|
4. **定期更新**:保持服务和依赖的最新版本
|
||||||
|
5. **监控日志**:定期检查异常访问
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
这种配置更加轻量和实用,避免了重复安装已有服务的资源浪费。
|
||||||
Reference in New Issue
Block a user