福建水务营收系统-部署设计

系统设计团队

2024年12月19日

1 福建水务营收系统部署设计文档

1.1 文档信息

项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成

1.2 目录

1.3 1. 部署概述

福建水务业务系统采用集中化部署模式,基于集团私有云环境进行部署,构建高可用、可扩展的系统架构,满足集团及下属各水务公司的业务需求。

1.3.1 1.1 部署目标

1.3.2 1.2 部署原则

1.4 2. 部署架构

1.4.1 2.1 总体部署架构

福建水务业务系统采用三层架构部署:

系统部署采用集群模式,各层均部署多个节点,实现高可用和负载均衡。

1.4.2 2.2 生产环境部署架构

生产环境采用双机房部署方案,包括主生产环境和灾备环境:

1.4.2.1 2.2.1 主生产环境

主生产环境部署在集团主数据中心,包括:

1.4.2.2 2.2.2 灾备环境

灾备环境部署在集团备用数据中心,包括:

1.4.3 2.3 测试环境部署架构

测试环境部署在集团测试中心,用于系统测试和验证,包括:

1.4.4 2.4 开发环境部署架构

开发环境部署在开发中心,用于系统开发和集成测试,包括:

1.5 3. 服务器配置

1.5.1 3.1 硬件配置要求

1.5.1.1 3.1.1 负载均衡服务器

1.5.1.2 3.1.2 Web服务器

1.5.1.3 3.1.3 应用服务器

1.5.1.4 3.1.4 数据库服务器

1.5.1.5 3.1.5 文件服务器

1.5.1.6 3.1.6 缓存服务器

1.5.2 3.2 软件配置要求

1.5.2.1 3.2.1 操作系统

1.5.2.2 3.2.2 数据库

1.5.2.3 3.2.3 应用服务器

1.5.2.4 3.2.4 缓存服务器

1.5.2.5 3.2.5 中间件

1.5.2.6 3.2.6 前端环境

1.6 4. 网络架构

1.6.1 4.1 网络拓扑

福建水务业务系统网络架构采用三层网络结构:

1.6.2 4.2 网络安全区域划分

网络安全区域划分为以下几个区域:

1.6.3 4.3 网络带宽配置

1.7 5. 安全设计

1.7.1 5.1 网络安全

1.7.1.1 5.1.1 边界安全

1.7.1.2 5.1.2 内网安全

1.7.2 5.2 系统安全

1.7.2.1 5.2.1 主机安全

1.7.2.2 5.2.2 应用安全

1.7.3 5.3 数据安全

1.7.3.1 5.3.1 数据存储安全

1.7.3.2 5.3.2 数据备份与恢复

1.8 6. 部署流程

1.8.1 6.1 部署准备

1.8.2 6.2 应用部署

1.8.2.1 6.2.1 数据库部署

1.8.2.2 6.2.2 应用服务部署

1.8.2.3 6.2.3 Web服务部署

1.8.3 6.3 系统联调

1.8.4 6.4 系统上线

1.9 7. 监控与运维

1.9.1 7.1 监控系统

1.9.1.1 7.1.1 基础设施监控

1.9.1.2 7.1.2 应用监控

1.9.1.3 7.1.3 数据库监控

1.9.2 7.2 运维管理

1.9.2.1 7.2.1 日常运维

1.9.2.2 7.2.2 变更管理

1.9.2.3 7.2.3 故障管理

1.9.2.4 7.2.4 应急预案

1.10 8. 容器化部署方案

1.10.1 8.1 Docker Compose部署

1.10.1.1 8.1.1 完整部署配置

# docker-compose.yml
version: '3.8'

services:
  # OpenGauss 数据库
  water-opengauss:
    image: enmotech/opengauss:5.0.0
    container_name: water-opengauss
    restart: always
    environment:
      GS_PASSWORD: "Water@2024"
      GS_DB: "ruoyi_water"
      GS_USERNAME: "water_user"
      TZ: "Asia/Shanghai"
    volumes:
      - ./data/opengauss:/var/lib/opengauss
      - ./sql:/docker-entrypoint-initdb.d
      - ./config/opengauss:/opt/opengauss/config
    ports:
      - "5432:5432"
    networks:
      - water-network
    healthcheck:
      test: ["CMD-SHELL", "gs_ctl status -D /var/lib/opengauss/data"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Redis 缓存
  water-redis:
    image: redis:7.0-alpine
    container_name: water-redis
    restart: always
    volumes:
      - ./data/redis:/data
      - ./config/redis/redis.conf:/etc/redis/redis.conf
    ports:
      - "6379:6379"
    command: redis-server /etc/redis/redis.conf
    networks:
      - water-network

  # 后端应用
  water-server:
    build:
      context: ./water-server
      dockerfile: Dockerfile
    container_name: water-server
    restart: always
    depends_on:
      - water-opengauss
      - water-redis
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - SPRING_DATASOURCE_URL=jdbc:opengauss://water-opengauss:5432/ruoyi_water?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
      - SPRING_DATASOURCE_USERNAME=water_user
      - SPRING_DATASOURCE_PASSWORD=Water@2024
      - SPRING_REDIS_HOST=water-redis
      - SPRING_REDIS_PORT=6379
      - SERVER_PORT=8080
    volumes:
      - ./logs:/app/logs
      - ./upload:/app/upload
    ports:
      - "8080:8080"
    networks:
      - water-network

  # 前端应用
  water-ui:
    build:
      context: ./water-ui
      dockerfile: Dockerfile
    container_name: water-ui
    restart: always
    depends_on:
      - water-server
    volumes:
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./config/nginx/conf.d:/etc/nginx/conf.d
    ports:
      - "80:80"
      - "443:443"
    networks:
      - water-network

  # Nginx 反向代理
  water-nginx:
    image: nginx:1.24-alpine
    container_name: water-nginx
    restart: always
    depends_on:
      - water-server
      - water-ui
    volumes:
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./config/nginx/conf.d:/etc/nginx/conf.d
      - ./ssl:/etc/nginx/ssl
      - ./logs/nginx:/var/log/nginx
    ports:
      - "80:80"
      - "443:443"
    networks:
      - water-network

  # MinIO 文件存储
  water-minio:
    image: minio/minio:latest
    container_name: water-minio
    restart: always
    environment:
      MINIO_ACCESS_KEY: "admin"
      MINIO_SECRET_KEY: "admin123456"
    volumes:
      - ./data/minio:/data
    ports:
      - "9000:9000"
      - "9001:9001"
    command: server /data --console-address ":9001"
    networks:
      - water-network

networks:
  water-network:
    driver: bridge

volumes:
  opengauss-data:
  redis-data:
  minio-data:

1.10.1.2 8.1.2 后端应用Dockerfile

# water-server/Dockerfile
FROM openjdk:17-jdk-slim

LABEL maintainer="fujian-water-dev-team"

# 设置工作目录
WORKDIR /app

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 添加应用jar包
COPY target/water-server.jar app.jar

# 创建日志目录
RUN mkdir -p /app/logs

# 暴露端口
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "-Xmx1024m", "-Xms512m", "-Dspring.profiles.active=prod", "/app/app.jar"]

1.10.1.3 8.1.3 前端应用Dockerfile

# water-ui/Dockerfile
# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

# 复制包管理文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制源代码
COPY . .

# 构建应用
RUN npm run build:prod

# 生产阶段
FROM nginx:1.24-alpine

# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html

# 复制nginx配置
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 80

# 启动nginx
CMD ["nginx", "-g", "daemon off;"]

1.10.2 8.2 Docker Compose高级配置

1.10.2.1 8.2.1 生产环境配置优化

Docker Compose生产环境配置文件

# docker-compose.prod.yml
version: '3.8'

services:
  water-opengauss:
    image: enmotech/opengauss:5.0.0
    container_name: water-opengauss-prod
    restart: unless-stopped
    environment:
      GS_PASSWORD: "${DB_PASSWORD:-Water@2024!}"
      GS_DB: "ruoyi_water"
      GS_USERNAME: "water_user"
      TZ: "Asia/Shanghai"
    volumes:
      - opengauss-prod-data:/var/lib/opengauss
      - ./config/opengauss/prod:/opt/opengauss/config
      - ./backups:/backups
    ports:
      - "5432:5432"
    networks:
      - water-prod-network
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '2.0'
    healthcheck:
      test: ["CMD-SHELL", "gs_ctl status -D /var/lib/opengauss/data"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s

  water-redis:
    image: redis:7.0-alpine
    container_name: water-redis-prod
    restart: unless-stopped
    command: redis-server /etc/redis/redis.conf --requirepass ${REDIS_PASSWORD:-water_redis_2024}
    volumes:
      - redis-prod-data:/data
      - ./config/redis/prod.conf:/etc/redis/redis.conf
    ports:
      - "6379:6379"
    networks:
      - water-prod-network
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '1.0'

  water-server:
    image: water-server:${VERSION:-latest}
    container_name: water-server-prod
    restart: unless-stopped
    depends_on:
      water-opengauss:
        condition: service_healthy
      water-redis:
        condition: service_started
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - SPRING_DATASOURCE_URL=jdbc:opengauss://water-opengauss:5432/ruoyi_water
      - SPRING_DATASOURCE_USERNAME=water_user
      - SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD:-Water@2024!}
      - SPRING_REDIS_HOST=water-redis
      - SPRING_REDIS_PASSWORD=${REDIS_PASSWORD:-water_redis_2024}
      - SERVER_PORT=8080
      - JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC
    volumes:
      - ./logs/prod:/app/logs
      - ./upload/prod:/app/upload
      - ./config/app:/app/config
    networks:
      - water-prod-network
    deploy:
      resources:
        limits:
          memory: 3G
          cpus: '2.0'
      replicas: 2
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  water-nginx:
    image: nginx:1.24-alpine
    container_name: water-nginx-prod
    restart: unless-stopped
    depends_on:
      - water-server
    volumes:
      - ./config/nginx/prod.conf:/etc/nginx/nginx.conf
      - ./config/nginx/conf.d:/etc/nginx/conf.d
      - ./ssl:/etc/nginx/ssl
      - ./logs/nginx:/var/log/nginx
      - ./static:/usr/share/nginx/html
    ports:
      - "80:80"
      - "443:443"
    networks:
      - water-prod-network
    deploy:
      resources:
        limits:
          memory: 256M
          cpus: '0.5'

networks:
  water-prod-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  opengauss-prod-data:
    driver: local
  redis-prod-data:
    driver: local

1.10.2.2 8.2.2 环境变量配置

# .env.prod
# 数据库配置
DB_PASSWORD=Water@2024!Production
DB_HOST=water-opengauss
DB_PORT=5432
DB_NAME=ruoyi_water

# Redis配置
REDIS_PASSWORD=WaterRedis@2024!Production
REDIS_HOST=water-redis
REDIS_PORT=6379

# 应用配置
APP_VERSION=1.0.0
JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError

# 网络配置
NGINX_PORT=80
NGINX_SSL_PORT=443

# 日志级别
LOG_LEVEL=INFO
LOG_ROOT_LEVEL=WARN

1.10.2.3 8.2.3 监控集成

# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: water-prometheus
    restart: unless-stopped
    volumes:
      - ./config/prometheus:/etc/prometheus
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
    networks:
      - water-network

  grafana:
    image: grafana/grafana:latest
    container_name: water-grafana
    restart: unless-stopped
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
    volumes:
      - grafana-data:/var/lib/grafana
      - ./config/grafana:/etc/grafana/provisioning
    ports:
      - "3000:3000"
    networks:
      - water-network

volumes:
  prometheus-data:
  grafana-data:

1.10.3 8.3 自动化部署脚本

1.10.3.1 8.3.1 Docker部署脚本

#!/bin/bash
# deploy-docker.sh

set -e

echo "=== 福建水务营收系统 Docker 部署脚本 ==="

# 检查Docker环境
if ! command -v docker &> /dev/null; then
    echo "错误: Docker未安装,请先安装Docker"
    exit 1
fi

if ! command -v docker-compose &> /dev/null; then
    echo "错误: Docker Compose未安装,请先安装Docker Compose"
    exit 1
fi

# 创建必要目录
echo "创建数据目录..."
mkdir -p data/{opengauss,redis,minio}
mkdir -p logs/{app,nginx}
mkdir -p config/{opengauss,redis,nginx/conf.d}
mkdir -p upload
mkdir -p ssl
mkdir -p backups

# 设置OpenGauss配置
echo "配置OpenGauss..."
cat > config/opengauss/postgresql.conf << EOF
# 数据库连接配置
max_connections = 1000
port = 5432
listen_addresses = '*'

# 内存配置
shared_buffers = 512MB
work_mem = 4MB
maintenance_work_mem = 128MB

# WAL配置
wal_level = replica
max_wal_size = 2GB
min_wal_size = 128MB

# 日志配置
log_destination = 'stderr'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_min_duration_statement = 3000

# 性能优化
effective_cache_size = 1GB
random_page_cost = 1.1
seq_page_cost = 1.0
EOF

cat > config/opengauss/pg_hba.conf << EOF
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     trust
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
host    all             all             0.0.0.0/0               md5
EOF

# 设置Redis配置
echo "配置Redis..."
cat > config/redis/redis.conf << EOF
port 6379
requirepass water_redis_2024
timeout 300
tcp-keepalive 300
maxmemory 256mb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000
EOF

# 设置Nginx配置
echo "配置Nginx..."
cat > config/nginx/nginx.conf << EOF
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
                    '\$status \$body_bytes_sent "\$http_referer" '
                    '"\$http_user_agent" "\$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;
    
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    client_max_body_size 50M;
    
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript 
               application/javascript application/xml+rss 
               application/json;
    
    include /etc/nginx/conf.d/*.conf;
}
EOF

cat > config/nginx/conf.d/water.conf << EOF
upstream water_backend {
    server water-server:8080 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

server {
    listen 80;
    server_name localhost;
    
    location /admin-api/ {
        proxy_pass http://water_backend;
        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 600;
        proxy_send_timeout 600;
        proxy_read_timeout 600;
    }
    
    location / {
        proxy_pass http://water-ui;
        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;
    }
}
EOF

# 构建和启动服务
echo "构建和启动Docker服务..."
docker-compose down
docker-compose build --no-cache
docker-compose up -d

# 等待服务启动
echo "等待服务启动..."
sleep 30

# 检查服务状态
echo "检查服务状态..."
docker-compose ps

echo "=== 部署完成 ==="
echo "系统访问地址: http://localhost"
echo "API接口地址: http://localhost/admin-api"
echo "MinIO控制台: http://localhost:9001 (admin/admin123456)"
echo ""
echo "查看日志: docker-compose logs -f [服务名]"
echo "停止服务: docker-compose down"
echo "重启服务: docker-compose restart"

1.10.3.2 8.3.2 生产环境部署脚本

#!/bin/bash
# deploy-prod.sh

set -e

echo "=== 福建水务营收系统 生产环境部署脚本 ==="

# 检查环境
if ! command -v docker &> /dev/null; then
    echo "错误: Docker未安装,请先安装Docker"
    exit 1
fi

if ! command -v docker-compose &> /dev/null; then
    echo "错误: Docker Compose未安装,请先安装Docker Compose"
    exit 1
fi

# 设置环境变量
export COMPOSE_PROJECT_NAME=water-system-prod
export VERSION=${1:-latest}

# 创建生产环境目录
echo "创建生产环境目录..."
mkdir -p {data,logs,config,upload,ssl,backups}/{prod,test}
mkdir -p config/{opengauss,redis,nginx,app,prometheus,grafana}

# 生成强密码
DB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
REDIS_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)

# 创建环境变量文件
echo "创建环境变量文件..."
cat > .env.prod << EOF
# 数据库配置
DB_PASSWORD=${DB_PASSWORD}
DB_HOST=water-opengauss
DB_PORT=5432
DB_NAME=ruoyi_water

# Redis配置
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_HOST=water-redis
REDIS_PORT=6379

# 应用配置
VERSION=${VERSION}
JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError

# 网络配置
NGINX_PORT=80
NGINX_SSL_PORT=443

# 日志级别
LOG_LEVEL=INFO
LOG_ROOT_LEVEL=WARN
EOF

echo "数据库密码: ${DB_PASSWORD}"
echo "Redis密码: ${REDIS_PASSWORD}"
echo "请妥善保存以上密码信息!"

# 创建SSL证书(自签名,生产环境应使用正式证书)
echo "创建SSL证书..."
if [ ! -f ssl/water-system.crt ]; then
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
        -keyout ssl/water-system.key \
        -out ssl/water-system.crt \
        -subj "/C=CN/ST=Fujian/L=Fuzhou/O=Water/CN=water.local"
fi

# 构建应用镜像
echo "构建应用镜像..."
docker build -t water-server:${VERSION} ./water-server
docker build -t water-ui:${VERSION} ./water-ui

# 停止现有服务
echo "停止现有服务..."
docker-compose --env-file .env.prod -f docker-compose.prod.yml down

# 启动生产服务
echo "启动生产服务..."
docker-compose --env-file .env.prod -f docker-compose.prod.yml up -d

# 等待服务启动
echo "等待服务启动..."
sleep 60

# 检查服务状态
echo "检查服务状态..."
docker-compose --env-file .env.prod -f docker-compose.prod.yml ps

# 健康检查
echo "执行健康检查..."
for i in {1..10}; do
    if curl -f http://localhost/actuator/health >/dev/null 2>&1; then
        echo "应用服务健康检查通过"
        break
    else
        echo "等待应用服务启动... ($i/10)"
        sleep 30
    fi
    
    if [ $i -eq 10 ]; then
        echo "警告: 应用服务健康检查失败"
        docker-compose --env-file .env.prod -f docker-compose.prod.yml logs water-server
    fi
done

echo "=== 生产环境部署完成 ==="
echo "系统访问地址: https://localhost"
echo "系统监控地址: http://localhost:3000 (admin/admin123)"
echo "数据库端口: 5432"
echo "Redis端口: 6379"
echo ""
echo "管理命令:"
echo "  查看日志: docker-compose --env-file .env.prod -f docker-compose.prod.yml logs -f [服务名]"
echo "  停止服务: docker-compose --env-file .env.prod -f docker-compose.prod.yml down"
echo "  重启服务: docker-compose --env-file .env.prod -f docker-compose.prod.yml restart [服务名]"
echo "  备份数据: docker exec water-opengauss-prod gs_dump -h localhost -U water_user ruoyi_water > ./backups/backup-\$(date +%Y%m%d_%H%M%S).sql"

1.10.4 8.4 持续集成/持续部署 (CI/CD)

1.10.4.1 8.4.1 GitHub Actions配置

# .github/workflows/deploy.yml
name: Build and Deploy Water System

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: docker.io
  IMAGE_NAME: water-system

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
    
    - name: Cache Maven dependencies
      uses: actions/cache@v3
      with:
        path: ~/.m2
        key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
        restore-keys: ${{ runner.os }}-m2
    
    - name: Run tests
      run: mvn clean test
    
    - name: Generate test report
      uses: dorny/test-reporter@v1
      if: success() || failure()
      with:
        name: Maven Tests
        path: target/surefire-reports/*.xml
        reporter: java-junit

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
    
    - name: Build with Maven
      run: mvn clean package -DskipTests
    
    - name: Build Docker image
      run: |
        docker build -t $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA ./water-server
        docker build -t $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA ./water-ui
    
    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}
    
    - name: Push Docker images
      run: |
        docker push $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA
        docker push $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA
        docker tag $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA $REGISTRY/$IMAGE_NAME-server:latest
        docker tag $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA $REGISTRY/$IMAGE_NAME-ui:latest
        docker push $REGISTRY/$IMAGE_NAME-server:latest
        docker push $REGISTRY/$IMAGE_NAME-ui:latest

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Deploy to Production
      env:
        DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
        DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
      run: |
        # 设置SSH密钥
        echo "$DEPLOY_KEY" > deploy_key
        chmod 600 deploy_key
        
        # 部署到生产服务器
        ssh -i deploy_key -o StrictHostKeyChecking=no $DEPLOY_USER@$DEPLOY_HOST << 'EOF'
          cd /opt/water-system
          
          # 拉取最新代码
          git pull origin main
          
          # 更新镜像版本
          export VERSION=$GITHUB_SHA
          
          # 重新部署
          ./deploy-prod.sh $VERSION
          
          # 验证部署
          sleep 30
          curl -f http://localhost/actuator/health || exit 1
          
          echo "生产环境部署完成!"
        EOF
        
        rm -f deploy_key
        echo "部署完成!"

这样,我已经为福建水务营收系统的部署设计文档补充了完整的现代化部署方案,包括:

  1. Docker Compose部署:完整的容器化部署配置
  2. Kubernetes部署:云原生部署配置
  3. 自动化部署脚本:简化部署流程
  4. CI/CD流水线:持续集成和持续部署