- 新增 deploy/docker/:Docker 本机模拟部署,含 Dockerfile、docker-compose、deploy.sh 一键脚本 - 新增 deploy/remote/:远程服务器部署,含 SSH 自动上传、重启、回滚脚本 - 新增 deploy/README.md:完整使用手册,含现状分析、落地调整工作清单、命令速查 - 新增 build.sh/start.sh:本地构建和启动脚本(含飞书通知) - 新增前端 .env.docker 环境配置,API 指向测试服务器 - 前端 package.json 新增 build-docker 命令 - 更新 .gitignore:排除 IDE 配置、SQL 数据、Docker 敏感文件 - 前端 UI 样式优化(多个页面组件) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
648 lines
19 KiB
Markdown
648 lines
19 KiB
Markdown
# SmartClean 本地模拟自动化打包部署方案
|
||
|
||
## 一、目标
|
||
|
||
在本机用 Docker 模拟真实服务器环境,实现 **一键构建 → 镜像打包 → 部署 → 健康检查 → 回滚 → 飞书通知** 全流程自动化,为后续迁移到远程服务器 / CI/CD 打基础。
|
||
|
||
## 二、整体架构
|
||
|
||
```
|
||
开发者本机
|
||
│
|
||
├── 源码 (smartclean/)
|
||
│
|
||
├── deploy.sh 一键触发
|
||
│ ├── 1. Maven/npm 构建产物
|
||
│ ├── 2. Docker 镜像打包(带版本 tag)
|
||
│ ├── 3. Docker Compose 部署(替换容器)
|
||
│ ├── 4. 健康检查(轮询接口)
|
||
│ ├── 5. 失败自动回滚(切回上一版本镜像)
|
||
│ └── 6. 飞书 Webhook 通知结果
|
||
│
|
||
└── Docker 容器组(模拟生产服务器)
|
||
┌──────────────────────────────────────────────┐
|
||
│ smartclean-front (Nginx, 端口 80) │
|
||
│ smartclean-web (Tomcat 8.5, 端口 18095) │
|
||
│ smartclean-task (Spring Boot, 端口 18097) │
|
||
│ smartclean-mysql (MySQL 5.7, 端口 3307) │
|
||
│ smartclean-redis (Redis 6, 端口 6380) │
|
||
└──────────────────────────────────────────────┘
|
||
```
|
||
|
||
> 端口刻意与本机开发环境错开,两套环境完全独立、互不干扰。
|
||
|
||
## 三、新增文件结构
|
||
|
||
```
|
||
smartclean/
|
||
└── deploy/
|
||
├── docker-compose.yml # 服务编排定义
|
||
├── .env # 环境变量(密码等敏感信息,不入 git)
|
||
│
|
||
├── Dockerfile.web # Web 服务镜像(Tomcat + ROOT.war)
|
||
├── Dockerfile.task # Task 服务镜像(JRE + JAR)
|
||
├── Dockerfile.front # 前端镜像(Nginx + 静态文件)
|
||
│
|
||
├── conf/
|
||
│ ├── nginx.conf # Nginx 反代配置(前端 → 后端)
|
||
│ ├── application-docker.yml # Web 服务 Docker 专用 Spring 配置
|
||
│ └── application-task-docker.yml # Task 服务 Docker 专用 Spring 配置
|
||
│
|
||
├── init-sql/
|
||
│ └── init.sh # 首次启动时自动建库导数据
|
||
│
|
||
├── deploy.sh # 一键部署脚本(主入口)
|
||
└── rollback.sh # 一键回滚脚本
|
||
```
|
||
|
||
## 四、各组件详细设计
|
||
|
||
### 4.1 Docker Compose 编排
|
||
|
||
```yaml
|
||
# deploy/docker-compose.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
# ==================== 基础设施 ====================
|
||
mysql:
|
||
image: mysql:5.7
|
||
container_name: smartclean-mysql
|
||
ports:
|
||
- "3307:3306"
|
||
environment:
|
||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||
volumes:
|
||
- mysql_data:/var/lib/mysql
|
||
- ../sql:/docker-entrypoint-initdb.d # 首次启动自动导入 SQL
|
||
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
||
healthcheck:
|
||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||
interval: 10s
|
||
retries: 5
|
||
networks:
|
||
- smartclean
|
||
|
||
redis:
|
||
image: redis:6-alpine
|
||
container_name: smartclean-redis
|
||
ports:
|
||
- "6380:6379"
|
||
command: redis-server --requirepass ${REDIS_PASSWORD}
|
||
volumes:
|
||
- redis_data:/data
|
||
healthcheck:
|
||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
|
||
interval: 10s
|
||
retries: 3
|
||
networks:
|
||
- smartclean
|
||
|
||
# ==================== 应用服务 ====================
|
||
web:
|
||
image: smartclean-web:${VERSION:-latest}
|
||
container_name: smartclean-web
|
||
build:
|
||
context: ..
|
||
dockerfile: deploy/Dockerfile.web
|
||
ports:
|
||
- "18095:8095"
|
||
depends_on:
|
||
mysql:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
environment:
|
||
SPRING_PROFILES_ACTIVE: docker
|
||
volumes:
|
||
- ./conf/application-docker.yml:/app/config/application-docker.yml
|
||
- web_logs:/app/logs
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-sf", "http://localhost:8095/dropDown/districtTree"]
|
||
interval: 15s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 60s
|
||
restart: on-failure:3
|
||
networks:
|
||
- smartclean
|
||
|
||
task:
|
||
image: smartclean-task:${VERSION:-latest}
|
||
container_name: smartclean-task
|
||
build:
|
||
context: ..
|
||
dockerfile: deploy/Dockerfile.task
|
||
ports:
|
||
- "18097:8097"
|
||
depends_on:
|
||
mysql:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_healthy
|
||
environment:
|
||
SPRING_PROFILES_ACTIVE: docker
|
||
volumes:
|
||
- ./conf/application-task-docker.yml:/app/config/application-task-docker.yml
|
||
- task_logs:/app/logs
|
||
restart: on-failure:3
|
||
networks:
|
||
- smartclean
|
||
|
||
frontend:
|
||
image: smartclean-front:${VERSION:-latest}
|
||
container_name: smartclean-front
|
||
build:
|
||
context: ..
|
||
dockerfile: deploy/Dockerfile.front
|
||
ports:
|
||
- "80:80"
|
||
depends_on:
|
||
- web
|
||
volumes:
|
||
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-sf", "http://localhost/"]
|
||
interval: 10s
|
||
retries: 3
|
||
restart: on-failure:3
|
||
networks:
|
||
- smartclean
|
||
|
||
volumes:
|
||
mysql_data:
|
||
redis_data:
|
||
web_logs:
|
||
task_logs:
|
||
|
||
networks:
|
||
smartclean:
|
||
driver: bridge
|
||
```
|
||
|
||
### 4.2 Dockerfile
|
||
|
||
#### Web 服务(Tomcat + WAR)
|
||
|
||
```dockerfile
|
||
# deploy/Dockerfile.web
|
||
FROM maven:3.8-openjdk-8 AS builder
|
||
WORKDIR /src
|
||
COPY backend/xiaoqu-intellectual-public/ xiaoqu-intellectual-public/
|
||
COPY backend/xiaoqu-intellectual-web/ xiaoqu-intellectual-web/
|
||
RUN cd xiaoqu-intellectual-public && mvn clean install -q -DskipTests \
|
||
&& cd ../xiaoqu-intellectual-web && mvn clean package -q -DskipTests
|
||
|
||
FROM tomcat:8.5-jdk8-temurin
|
||
RUN rm -rf /usr/local/tomcat/webapps/*
|
||
COPY --from=builder /src/xiaoqu-intellectual-web/target/ROOT.war /usr/local/tomcat/webapps/
|
||
# 注入外部配置目录
|
||
ENV SPRING_CONFIG_ADDITIONAL_LOCATION=/app/config/
|
||
RUN mkdir -p /app/config /app/logs
|
||
EXPOSE 8095
|
||
```
|
||
|
||
#### Task 服务(Spring Boot JAR)
|
||
|
||
```dockerfile
|
||
# deploy/Dockerfile.task
|
||
FROM maven:3.8-openjdk-8 AS builder
|
||
WORKDIR /src
|
||
COPY backend/xiaoqu-intellectual-public/ xiaoqu-intellectual-public/
|
||
COPY backend/xiaoqu-intellectual-task/ xiaoqu-intellectual-task/
|
||
RUN cd xiaoqu-intellectual-public && mvn clean install -q -DskipTests \
|
||
&& cd ../xiaoqu-intellectual-task && mvn clean package -q -DskipTests
|
||
|
||
FROM openjdk:8-jre-slim
|
||
WORKDIR /app
|
||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||
COPY --from=builder /src/xiaoqu-intellectual-task/target/*.jar app.jar
|
||
RUN mkdir -p /app/config /app/logs
|
||
EXPOSE 8097
|
||
ENTRYPOINT ["java", "-jar", "app.jar", \
|
||
"--spring.config.additional-location=/app/config/"]
|
||
```
|
||
|
||
#### 前端(多阶段构建 → Nginx)
|
||
|
||
```dockerfile
|
||
# deploy/Dockerfile.front
|
||
FROM node:16-alpine AS builder
|
||
WORKDIR /app
|
||
COPY frontend/witcleansystem/package*.json ./
|
||
RUN npm ci --registry=https://registry.npmmirror.com
|
||
COPY frontend/witcleansystem/ ./
|
||
RUN npm run build
|
||
|
||
FROM nginx:1.24-alpine
|
||
RUN rm -rf /usr/share/nginx/html/*
|
||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||
EXPOSE 80
|
||
```
|
||
|
||
### 4.3 Nginx 反代配置
|
||
|
||
```nginx
|
||
# deploy/conf/nginx.conf
|
||
server {
|
||
listen 80;
|
||
server_name localhost;
|
||
|
||
# 前端静态文件
|
||
location / {
|
||
root /usr/share/nginx/html;
|
||
index index.html;
|
||
try_files $uri $uri/ /index.html; # SPA history fallback
|
||
}
|
||
|
||
# API 反代到后端 Web 服务
|
||
location /api/ {
|
||
proxy_pass http://web:8095/;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
}
|
||
|
||
# 静态资源缓存
|
||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
|
||
root /usr/share/nginx/html;
|
||
expires 7d;
|
||
add_header Cache-Control "public, immutable";
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.4 Docker 专用 Spring 配置
|
||
|
||
```yaml
|
||
# deploy/conf/application-docker.yml
|
||
# 覆盖 application-test.yml 中的远程地址,指向 Docker 容器
|
||
server:
|
||
port: 8095
|
||
|
||
redis:
|
||
host: redis # Docker 容器名
|
||
port: 6379
|
||
password: ${REDIS_PASSWORD:kaixinjiuhao}
|
||
|
||
spring:
|
||
datasource:
|
||
db1:
|
||
url: jdbc:mysql://mysql:3306/xiaoqu_comples_d?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||
username: root
|
||
password: ${DB_PASSWORD:kaixinjiuhao}
|
||
db2:
|
||
url: jdbc:mysql://mysql:3306/xiaoqu_intellectual_d?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||
username: root
|
||
password: ${DB_PASSWORD:kaixinjiuhao}
|
||
|
||
xxl:
|
||
job:
|
||
admin:
|
||
addresses: http://xxl-job-admin:8080/xxl-job-admin # 可选,本地模拟可留空
|
||
```
|
||
|
||
### 4.5 环境变量文件
|
||
|
||
```bash
|
||
# deploy/.env(不入 git)
|
||
DB_PASSWORD=kaixinjiuhao
|
||
REDIS_PASSWORD=kaixinjiuhao
|
||
VERSION=latest
|
||
FEISHU_WEBHOOK=https://open.feishu.cn/open-apis/bot/v2/hook/5703e8cc-6998-46a6-af9d-8c5102cc8c1e
|
||
```
|
||
|
||
## 五、一键部署脚本
|
||
|
||
```bash
|
||
# deploy/deploy.sh
|
||
#!/bin/bash
|
||
#
|
||
# SmartClean 一键部署脚本(本地 Docker 模拟)
|
||
#
|
||
# 用法:
|
||
# ./deploy.sh # 部署所有服务
|
||
# ./deploy.sh web # 仅重建部署 Web 服务
|
||
# ./deploy.sh task # 仅重建部署 Task 服务
|
||
# ./deploy.sh front # 仅重建部署前端
|
||
# ./deploy.sh rollback # 回滚到上一版本
|
||
|
||
set -e
|
||
|
||
DEPLOY_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
ROOT_DIR="$(dirname "$DEPLOY_DIR")"
|
||
source "$DEPLOY_DIR/.env"
|
||
|
||
# ===== 版本号:日期-git短hash =====
|
||
GIT_HASH=$(cd "$ROOT_DIR" && git rev-parse --short HEAD)
|
||
VERSION="v$(date +%Y%m%d)-${GIT_HASH}"
|
||
BACKUP_FILE="$DEPLOY_DIR/.last-version"
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m'
|
||
|
||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||
|
||
# ===== 飞书通知 =====
|
||
notify_feishu() {
|
||
local title="$1" content="$2" color="$3"
|
||
curl -s -X POST "$FEISHU_WEBHOOK" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{
|
||
\"msg_type\": \"interactive\",
|
||
\"card\": {
|
||
\"header\": {\"title\":{\"tag\":\"plain_text\",\"content\":\"$title\"},\"template\":\"$color\"},
|
||
\"elements\": [{\"tag\":\"markdown\",\"content\":\"$content\"}]
|
||
}
|
||
}" > /dev/null 2>&1
|
||
}
|
||
|
||
# ===== 备份当前版本号 =====
|
||
backup_version() {
|
||
if [ -f "$DEPLOY_DIR/.current-version" ]; then
|
||
cp "$DEPLOY_DIR/.current-version" "$BACKUP_FILE"
|
||
log_info "已备份当前版本: $(cat "$BACKUP_FILE")"
|
||
fi
|
||
}
|
||
|
||
# ===== 构建镜像 =====
|
||
build_images() {
|
||
local target="${1:-all}"
|
||
local start_time=$(date +%s)
|
||
|
||
cd "$DEPLOY_DIR"
|
||
|
||
case "$target" in
|
||
web)
|
||
log_info "构建 Web 镜像 ($VERSION)..."
|
||
docker compose build web
|
||
;;
|
||
task)
|
||
log_info "构建 Task 镜像 ($VERSION)..."
|
||
docker compose build task
|
||
;;
|
||
front)
|
||
log_info "构建前端镜像 ($VERSION)..."
|
||
docker compose build frontend
|
||
;;
|
||
all)
|
||
log_info "构建全部镜像 ($VERSION)..."
|
||
docker compose build web task frontend
|
||
;;
|
||
esac
|
||
|
||
local elapsed=$(( $(date +%s) - start_time ))
|
||
log_info "镜像构建完成 (${elapsed}s)"
|
||
}
|
||
|
||
# ===== 部署服务 =====
|
||
deploy_services() {
|
||
local target="${1:-all}"
|
||
|
||
cd "$DEPLOY_DIR"
|
||
export VERSION
|
||
|
||
# 确保基础设施先启动
|
||
log_info "确保 MySQL + Redis 运行中..."
|
||
docker compose up -d mysql redis
|
||
log_info "等待数据库就绪..."
|
||
docker compose exec mysql mysqladmin ping -h localhost --wait=30 --silent 2>/dev/null
|
||
|
||
case "$target" in
|
||
web) docker compose up -d --no-deps web ;;
|
||
task) docker compose up -d --no-deps task ;;
|
||
front) docker compose up -d --no-deps frontend ;;
|
||
all) docker compose up -d web task frontend ;;
|
||
esac
|
||
|
||
log_info "容器已启动,开始健康检查..."
|
||
}
|
||
|
||
# ===== 健康检查 =====
|
||
healthcheck() {
|
||
local target="${1:-all}"
|
||
local max_retries=20
|
||
local interval=5
|
||
|
||
# 检查 Web 服务
|
||
if [ "$target" = "all" ] || [ "$target" = "web" ]; then
|
||
log_info "检查 Web 服务..."
|
||
for i in $(seq 1 $max_retries); do
|
||
if curl -sf http://localhost:18095/dropDown/districtTree > /dev/null 2>&1; then
|
||
log_info "✅ Web 服务健康 (第${i}次检查)"
|
||
break
|
||
fi
|
||
if [ $i -eq $max_retries ]; then
|
||
log_error "❌ Web 服务健康检查失败"
|
||
return 1
|
||
fi
|
||
sleep $interval
|
||
done
|
||
fi
|
||
|
||
# 检查前端
|
||
if [ "$target" = "all" ] || [ "$target" = "front" ]; then
|
||
log_info "检查前端服务..."
|
||
for i in $(seq 1 $max_retries); do
|
||
if curl -sf http://localhost:80/ > /dev/null 2>&1; then
|
||
log_info "✅ 前端服务健康 (第${i}次检查)"
|
||
break
|
||
fi
|
||
if [ $i -eq $max_retries ]; then
|
||
log_error "❌ 前端服务健康检查失败"
|
||
return 1
|
||
fi
|
||
sleep $interval
|
||
done
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
# ===== 回滚 =====
|
||
rollback() {
|
||
if [ ! -f "$BACKUP_FILE" ]; then
|
||
log_error "没有可回滚的版本"
|
||
exit 1
|
||
fi
|
||
|
||
local old_version=$(cat "$BACKUP_FILE")
|
||
log_warn "回滚到版本: $old_version"
|
||
|
||
export VERSION="$old_version"
|
||
cd "$DEPLOY_DIR"
|
||
docker compose up -d web task frontend
|
||
|
||
echo "$old_version" > "$DEPLOY_DIR/.current-version"
|
||
log_info "回滚完成"
|
||
|
||
notify_feishu "⚠️ SmartClean 已回滚" \
|
||
"**回滚版本:** $old_version\\n**触发原因:** 健康检查失败" \
|
||
"yellow"
|
||
}
|
||
|
||
# ===== 主流程 =====
|
||
TARGET="${1:-all}"
|
||
DEPLOY_START=$(date +%s)
|
||
BRANCH=$(cd "$ROOT_DIR" && git rev-parse --abbrev-ref HEAD)
|
||
COMMIT=$(cd "$ROOT_DIR" && git log -1 --format='%h %s')
|
||
|
||
if [ "$TARGET" = "rollback" ]; then
|
||
rollback
|
||
exit 0
|
||
fi
|
||
|
||
log_info "=============================="
|
||
log_info " SmartClean 自动化部署"
|
||
log_info " 版本: $VERSION"
|
||
log_info " 分支: $BRANCH"
|
||
log_info " 目标: $TARGET"
|
||
log_info "=============================="
|
||
|
||
# 1. 备份当前版本
|
||
backup_version
|
||
|
||
# 2. 构建镜像
|
||
build_images "$TARGET"
|
||
|
||
# 3. 部署
|
||
deploy_services "$TARGET"
|
||
|
||
# 4. 健康检查
|
||
if healthcheck "$TARGET"; then
|
||
# 记录当前版本
|
||
echo "$VERSION" > "$DEPLOY_DIR/.current-version"
|
||
|
||
ELAPSED=$(( $(date +%s) - DEPLOY_START ))
|
||
log_info "=============================="
|
||
log_info " ✅ 部署成功!耗时 ${ELAPSED}s"
|
||
log_info " 前端: http://localhost"
|
||
log_info " Web: http://localhost:18095"
|
||
log_info " Task: http://localhost:18097"
|
||
log_info "=============================="
|
||
|
||
notify_feishu "✅ SmartClean 部署成功" \
|
||
"**版本:** $VERSION\\n**分支:** $BRANCH\\n**提交:** $COMMIT\\n**目标:** $TARGET\\n**耗时:** ${ELAPSED}s" \
|
||
"green"
|
||
else
|
||
log_error "健康检查失败,自动回滚..."
|
||
rollback
|
||
|
||
ELAPSED=$(( $(date +%s) - DEPLOY_START ))
|
||
notify_feishu "❌ SmartClean 部署失败(已回滚)" \
|
||
"**版本:** $VERSION\\n**分支:** $BRANCH\\n**提交:** $COMMIT\\n**耗时:** ${ELAPSED}s\\n**状态:** 已自动回滚" \
|
||
"red"
|
||
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
## 六、回滚脚本
|
||
|
||
```bash
|
||
# deploy/rollback.sh
|
||
#!/bin/bash
|
||
# 快捷回滚入口
|
||
DEPLOY_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
exec "$DEPLOY_DIR/deploy.sh" rollback
|
||
```
|
||
|
||
## 七、使用方式
|
||
|
||
### 首次启动
|
||
|
||
```bash
|
||
cd deploy/
|
||
|
||
# 1. 创建 .env 文件(设置密码等)
|
||
cp .env.example .env
|
||
|
||
# 2. 一键构建 + 部署全部服务
|
||
./deploy.sh
|
||
```
|
||
|
||
### 日常使用
|
||
|
||
```bash
|
||
# 修改了后端代码,只重建部署 Web 服务
|
||
./deploy.sh web
|
||
|
||
# 修改了前端代码,只重建部署前端
|
||
./deploy.sh front
|
||
|
||
# 全量部署
|
||
./deploy.sh
|
||
|
||
# 出问题了,一键回滚
|
||
./deploy.sh rollback
|
||
# 或
|
||
./rollback.sh
|
||
```
|
||
|
||
### 查看日志
|
||
|
||
```bash
|
||
# 查看所有服务日志
|
||
docker compose -f deploy/docker-compose.yml logs -f
|
||
|
||
# 只看 Web 服务
|
||
docker compose -f deploy/docker-compose.yml logs -f web
|
||
|
||
# 查看容器状态
|
||
docker compose -f deploy/docker-compose.yml ps
|
||
```
|
||
|
||
### 停止 / 清理
|
||
|
||
```bash
|
||
# 停止所有容器(数据保留)
|
||
docker compose -f deploy/docker-compose.yml down
|
||
|
||
# 停止并删除数据卷(慎用,会丢数据库数据)
|
||
docker compose -f deploy/docker-compose.yml down -v
|
||
```
|
||
|
||
## 八、端口映射总览
|
||
|
||
| 服务 | 容器内端口 | 宿主机端口 | 用途 |
|
||
|------|-----------|-----------|------|
|
||
| 前端 (Nginx) | 80 | **80** | 浏览器访问入口 |
|
||
| Web 后端 | 8095 | **18095** | API 接口(也可通过 Nginx `/api` 访问) |
|
||
| Task 后端 | 8097 | **18097** | 定时任务服务 |
|
||
| MySQL | 3306 | **3307** | 本机连接调试用 |
|
||
| Redis | 6379 | **6380** | 本机连接调试用 |
|
||
|
||
> 与本机开发环境 (8079/8095/3306/6379) 完全隔离。
|
||
|
||
## 九、与本机开发环境的对比
|
||
|
||
```
|
||
┌─────────────────────────────┐ ┌─────────────────────────────┐
|
||
│ 本机开发环境(已有) │ │ Docker 模拟部署(新增) │
|
||
│ │ │ │
|
||
│ npm run dev → :8079 │ │ Nginx → :80 │
|
||
│ mvn spring-boot:run → :8095│ │ Tomcat 容器 → :18095 │
|
||
│ 本机 MySQL → :3306 │ │ MySQL 容器 → :3307 │
|
||
│ 本机 Redis → :6379 │ │ Redis 容器 → :6380 │
|
||
│ │ │ │
|
||
│ 用途: 开发调试、热重载 │ │ 用途: 模拟生产部署流程 │
|
||
└─────────────────────────────┘ └─────────────────────────────┘
|
||
```
|
||
|
||
## 十、后续演进路径
|
||
|
||
本方案在本机验证通过后,可以低成本迁移到真实环境:
|
||
|
||
| 阶段 | 动作 | 改动量 |
|
||
|------|------|--------|
|
||
| **当前** | 本机 Docker 模拟 | 本方案 |
|
||
| **阶段 2** | 远程服务器部署 | deploy.sh 加 SSH 远程执行,或把镜像 push 到私有 Registry |
|
||
| **阶段 3** | Gitea Actions CI/CD | 把 deploy.sh 的逻辑搬到 `.gitea/workflows/deploy.yml`,push 自动触发 |
|
||
| **阶段 4** | 多环境 | docker-compose.prod.yml 覆盖生产配置,同一套镜像部署到不同环境 |
|
||
|
||
每个阶段都是增量改动,核心的 Dockerfile 和 docker-compose.yml 不需要重写。
|