Files
photography/docs/deployment.md
xujiang 72414d0979 feat: 完成后端-管理后台集成及部署配置
🚀 主要功能:
- 完善后端API服务层,实现完整的CRUD操作
- 开发管理后台所有核心页面 (仪表板、照片、分类、标签、用户、设置)
- 完成前后端完全集成,所有API接口正常对接
- 配置完整的CI/CD流水线,支持自动化部署

🎯 后端完善:
- 实现PhotoService, CategoryService, TagService, UserService
- 添加完整的API处理器和路由配置
- 支持Docker容器化部署
- 添加数据库迁移和健康检查

🎨 管理后台完成:
- 仪表板: 实时统计数据展示
- 照片管理: 完整的CRUD操作,支持批量处理
- 分类管理: 树形结构展示和管理
- 标签管理: 颜色标签和统计信息
- 用户管理: 角色权限控制
- 系统设置: 多标签配置界面
- 添加pre-commit代码质量检查

🔧 部署配置:
- Docker Compose完整配置
- 后端CI/CD流水线 (Docker部署)
- 管理后台CI/CD流水线 (静态文件部署)
- 前端CI/CD流水线优化
- 自动化脚本: 部署、备份、监控
- 完整的部署文档和运维指南

 集成完成:
- 所有API接口正常连接
- 认证系统完整集成
- 数据获取和状态管理
- 错误处理和用户反馈
- 响应式设计优化
2025-07-09 16:23:18 +08:00

760 lines
16 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.

# 摄影作品集项目部署文档
本文档详细说明了摄影作品集项目的完整部署流程,包括前端、管理后台、后端 API 和数据库的部署配置。
## 📋 目录
- [系统要求](#系统要求)
- [环境配置](#环境配置)
- [后端部署](#后端部署)
- [前端部署](#前端部署)
- [管理后台部署](#管理后台部署)
- [数据库配置](#数据库配置)
- [Web 服务器配置](#web-服务器配置)
- [SSL 证书配置](#ssl-证书配置)
- [监控和备份](#监控和备份)
- [故障排除](#故障排除)
## 🖥️ 系统要求
### 硬件要求
- **CPU**: 2 核心以上
- **内存**: 4GB 以上 (推荐 8GB)
- **存储**: 20GB 以上 SSD 存储
- **网络**: 稳定的互联网连接
### 软件要求
- **操作系统**: Ubuntu 20.04 LTS / CentOS 8 / Debian 11
- **Docker**: 20.10 或更高版本
- **Docker Compose**: 2.0 或更高版本
- **Git**: 2.20 或更高版本
- **域名**: 用于生产环境部署
## ⚙️ 环境配置
### 1. 安装 Docker 和 Docker Compose
```bash
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker --version
docker-compose --version
```
### 2. 克隆项目仓库
```bash
git clone <repository-url> photography
cd photography
```
### 3. 创建环境变量文件
```bash
# 复制环境变量模板
cp .env.example .env
# 编辑环境变量
nano .env
```
## 🚀 后端部署
### 1. 后端 Docker 配置
查看后端 Dockerfile
```dockerfile
# backend/Dockerfile
FROM golang:1.21-alpine AS builder
# 设置工作目录
WORKDIR /app
# 安装依赖
RUN apk add --no-cache git ca-certificates tzdata
# 复制 go mod 文件
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main cmd/server/main.go
# 生产环境镜像
FROM alpine:latest
# 安装必要的包
RUN apk --no-cache add ca-certificates wget
# 创建用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 设置工作目录
WORKDIR /app
# 从构建阶段复制文件
COPY --from=builder /app/main .
COPY --from=builder /app/configs ./configs
COPY --from=builder /app/migrations ./migrations
# 创建必要的目录
RUN mkdir -p uploads logs && chown -R appuser:appgroup /app
# 切换到非 root 用户
USER appuser
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# 启动命令
CMD ["./main"]
```
### 2. 后端 Docker Compose 服务
```yaml
# docker-compose.yml - 后端部分
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
volumes:
postgres_data:
driver: local
redis_data:
driver: local
networks:
photography_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
```
### 3. 启动后端服务
```bash
# 构建并启动后端服务
docker-compose up -d postgres redis
docker-compose up -d backend
# 查看日志
docker-compose logs -f backend
# 验证服务状态
curl http://localhost:8080/health
```
## 🌐 前端部署
### 1. 前端构建配置
```bash
# 进入前端目录
cd frontend/
# 安装依赖
bun install
# 构建生产版本
bun run build
# 验证构建结果
ls -la out/
```
### 2. 前端部署脚本
创建前端部署脚本:
```bash
#!/bin/bash
# scripts/deploy-frontend.sh
set -e
echo "🚀 开始部署前端..."
# 配置变量
FRONTEND_DIR="/home/gitea/www/photography"
BACKUP_DIR="/home/gitea/backups/photography-frontend"
BUILD_DIR="./frontend/out"
# 创建备份
echo "📦 创建当前版本备份..."
mkdir -p "$BACKUP_DIR"
if [ -d "$FRONTEND_DIR" ]; then
tar -czf "$BACKUP_DIR/frontend-$(date +%Y%m%d-%H%M%S).tar.gz" -C "$FRONTEND_DIR" .
fi
# 创建部署目录
echo "📁 准备部署目录..."
mkdir -p "$FRONTEND_DIR"
# 部署新版本
echo "🔄 部署新版本..."
rsync -av --delete "$BUILD_DIR/" "$FRONTEND_DIR/"
# 设置权限
echo "🔐 设置文件权限..."
chown -R gitea:gitea "$FRONTEND_DIR"
chmod -R 755 "$FRONTEND_DIR"
# 清理旧备份 (保留最近5个)
echo "🧹 清理旧备份..."
cd "$BACKUP_DIR"
ls -t frontend-*.tar.gz | tail -n +6 | xargs -r rm
echo "✅ 前端部署完成!"
echo "🌐 访问地址: https://photography.iriver.top"
```
## 🛠️ 管理后台部署
### 1. 管理后台构建配置
```bash
# 进入管理后台目录
cd admin/
# 安装依赖
npm install
# 构建生产版本
npm run build
# 验证构建结果
ls -la dist/
```
### 2. 管理后台部署脚本
```bash
#!/bin/bash
# scripts/deploy-admin.sh
set -e
echo "🚀 开始部署管理后台..."
# 配置变量
ADMIN_DIR="/home/gitea/www/photography-admin"
BACKUP_DIR="/home/gitea/backups/photography-admin"
BUILD_DIR="./admin/dist"
# 创建备份
echo "📦 创建当前版本备份..."
mkdir -p "$BACKUP_DIR"
if [ -d "$ADMIN_DIR" ]; then
tar -czf "$BACKUP_DIR/admin-$(date +%Y%m%d-%H%M%S).tar.gz" -C "$ADMIN_DIR" .
fi
# 创建部署目录
echo "📁 准备部署目录..."
mkdir -p "$ADMIN_DIR"
# 部署新版本
echo "🔄 部署新版本..."
rsync -av --delete "$BUILD_DIR/" "$ADMIN_DIR/"
# 设置权限
echo "🔐 设置文件权限..."
chown -R gitea:gitea "$ADMIN_DIR"
chmod -R 755 "$ADMIN_DIR"
# 清理旧备份 (保留最近5个)
echo "🧹 清理旧备份..."
cd "$BACKUP_DIR"
ls -t admin-*.tar.gz | tail -n +6 | xargs -r rm
echo "✅ 管理后台部署完成!"
echo "🌐 访问地址: https://admin.photography.iriver.top"
```
## 🗄️ 数据库配置
### 1. 数据库初始化
```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";
-- 设置时区
SET timezone = 'Asia/Shanghai';
```
### 2. 数据库备份脚本
```bash
#!/bin/bash
# scripts/backup.sh
set -e
# 配置变量
DB_HOST="${DB_HOST:-postgres}"
DB_NAME="${DB_NAME:-photography}"
DB_USER="${DB_USER:-postgres}"
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d-%H%M%S)
echo "🗄️ 开始数据库备份..."
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 执行备份
pg_dump -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" \
--no-password --verbose --clean --no-acl --no-owner \
-f "$BACKUP_DIR/photography-$DATE.sql"
# 压缩备份文件
gzip "$BACKUP_DIR/photography-$DATE.sql"
# 清理旧备份 (保留最近7天)
find "$BACKUP_DIR" -name "photography-*.sql.gz" -mtime +7 -delete
echo "✅ 数据库备份完成: photography-$DATE.sql.gz"
```
## 🌐 Web 服务器配置
### Caddy 配置文件
```caddyfile
# docs/deployment/Caddyfile
# 前端网站
photography.iriver.top {
# 根目录
root * /home/gitea/www/photography
# 静态文件服务
file_server
# SPA 路由支持
try_files {path} /index.html
# 压缩
encode gzip
# 缓存配置
header {
# 静态资源缓存
Cache-Control "public, max-age=31536000" {
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.woff *.woff2
}
# HTML 文件不缓存
Cache-Control "no-cache" {
path *.html
}
# 安全头
X-Frame-Options "DENY"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
}
# 日志
log {
output file /var/log/caddy/photography.log
format json
}
}
# 管理后台
admin.photography.iriver.top {
# 根目录
root * /home/gitea/www/photography-admin
# 静态文件服务
file_server
# SPA 路由支持
try_files {path} /index.html
# 压缩
encode gzip
# 基本认证 (可选)
# basicauth {
# admin $2a$14$encrypted_password_hash
# }
# 缓存配置
header {
Cache-Control "public, max-age=31536000" {
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.woff *.woff2
}
Cache-Control "no-cache" {
path *.html
}
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
# 日志
log {
output file /var/log/caddy/admin.photography.log
format json
}
}
# API 服务
api.photography.iriver.top {
# 反向代理到后端服务
reverse_proxy localhost:8080 {
# 健康检查
health_uri /health
health_interval 30s
health_timeout 10s
# 请求头
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote_host}
}
# CORS 处理
header {
Access-Control-Allow-Origin "https://photography.iriver.top, https://admin.photography.iriver.top"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Content-Type, Authorization"
Access-Control-Max-Age "86400"
}
# 预检请求处理
@options method OPTIONS
respond @options 204
# 上传文件大小限制
request_body {
max_size 10MB
}
# 日志
log {
output file /var/log/caddy/api.photography.log
format json
}
}
# 全局配置
{
# 自动 HTTPS
auto_https on
# Let's Encrypt 邮箱
email admin@iriver.top
# 日志级别
log {
level INFO
}
}
```
## 🔒 SSL 证书配置
Caddy 会自动处理 SSL 证书,但也可以手动配置:
```bash
# 手动获取证书 (如果需要)
certbot certonly --webroot -w /var/www/html -d photography.iriver.top -d admin.photography.iriver.top -d api.photography.iriver.top
# 设置自动续期
echo "0 3 * * * certbot renew --quiet && systemctl reload caddy" | crontab -
```
## 📊 监控和备份
### 1. 系统监控脚本
```bash
#!/bin/bash
# scripts/monitor.sh
# 检查服务状态
check_service() {
local service=$1
local url=$2
echo "检查 $service..."
if curl -f -s "$url" > /dev/null; then
echo "✅ $service 正常运行"
else
echo "❌ $service 服务异常"
# 发送告警 (可集成邮件、微信等)
# send_alert "$service 服务异常"
fi
}
# 检查磁盘空间
check_disk() {
local usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
echo "磁盘使用率: $usage%"
if [ "$usage" -gt 80 ]; then
echo "⚠️ 磁盘空间不足"
# send_alert "磁盘空间不足: $usage%"
fi
}
# 检查内存使用
check_memory() {
local usage=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
echo "内存使用率: $usage%"
}
# 执行检查
echo "🔍 开始系统监控..."
check_service "前端" "https://photography.iriver.top"
check_service "管理后台" "https://admin.photography.iriver.top"
check_service "API" "https://api.photography.iriver.top/health"
check_disk
check_memory
echo "✅ 监控检查完成"
```
### 2. 自动备份任务
```bash
# 设置定时任务
crontab -e
# 添加以下内容:
# 每天凌晨2点备份数据库
0 2 * * * /path/to/photography/scripts/backup.sh
# 每周日凌晨3点重启服务 (可选)
0 3 * * 0 cd /path/to/photography && docker-compose restart
# 每小时检查一次服务状态
0 * * * * /path/to/photography/scripts/monitor.sh
```
## 🐛 故障排除
### 常见问题和解决方案
#### 1. 后端服务无法启动
```bash
# 查看日志
docker-compose logs backend
# 检查配置
docker-compose config
# 重新构建
docker-compose build backend --no-cache
```
#### 2. 数据库连接失败
```bash
# 检查数据库状态
docker-compose ps postgres
# 检查数据库日志
docker-compose logs postgres
# 手动连接测试
docker-compose exec postgres psql -U postgres -d photography
```
#### 3. 前端/管理后台访问异常
```bash
# 检查文件权限
ls -la /home/gitea/www/photography/
ls -la /home/gitea/www/photography-admin/
# 检查 Caddy 配置
caddy validate --config /etc/caddy/Caddyfile
# 重新加载 Caddy
systemctl reload caddy
```
#### 4. SSL 证书问题
```bash
# 检查证书状态
curl -I https://photography.iriver.top
# 查看 Caddy 日志
tail -f /var/log/caddy/photography.log
# 手动重新申请证书
systemctl stop caddy
caddy run --config /etc/caddy/Caddyfile
```
### 日志文件位置
- **后端日志**: `./backend/logs/`
- **Caddy 日志**: `/var/log/caddy/`
- **数据库日志**: `docker-compose logs postgres`
- **系统日志**: `/var/log/syslog`
## 🚀 部署命令速查
```bash
# 完整部署流程
git pull origin main
cd photography
# 后端部署
docker-compose build backend
docker-compose up -d
# 前端部署
cd frontend && bun run build && cd ..
./scripts/deploy-frontend.sh
# 管理后台部署
cd admin && npm run build && cd ..
./scripts/deploy-admin.sh
# 重启 Web 服务器
sudo systemctl reload caddy
# 检查服务状态
docker-compose ps
curl https://photography.iriver.top
curl https://admin.photography.iriver.top
curl https://api.photography.iriver.top/health
```
## 📞 技术支持
如果在部署过程中遇到问题,请:
1. 查看相关日志文件
2. 检查系统资源使用情况
3. 验证配置文件语法
4. 联系技术支持团队
---
📝 **文档版本**: v1.0
🕒 **最后更新**: 2024年
👥 **维护团队**: 摄影作品集项目组