部署
线上全部服务通过 1panel 的 Docker 部署,对外统一由 1panel 的 OpenResty 在 80/443 反向代理并处理证书,业务容器只绑定 127.0.0.1。
服务器地址与登录凭据不写进本文档
具体的服务器入口、后台账号口令、私钥路径、容器凭据只保存在 .trae/rules/deployment.md(.trae 已在 .gitignore 中,该文件不得提交、不得复制到代码或文档里)。本页只描述与代码相关的部署机制。
运行时中间件
| 中间件 / 服务 | 用途 | 备注 |
|---|---|---|
| MySQL | 业务数据、Flowable 流程数据 | 唯一需要 DDL 权限的初始化环节是 Flowable 建表 |
| Redis | 会话、缓存、限流、Redisson 分布式能力 | 必须与后端网络互通 |
| XXL-JOB Admin | 定时任务调度中心 | 执行器通过 access-token 注册,生产必须开启 |
| OpenResty / Nginx | 前端静态资源、/api 与 /actuator 反向代理 | 前端镜像内置 Nginx,只负责静态资源与自身健康检查 |
| SMTP | 邮件验证码、审批通知 | 按需 |
| 阿里云 OSS | 文件上传与预览 | 按需 |
| 阿里云验证码 / 号码认证 | 登录人机校验、短信验证码 | 按需 |
| Sentry / GlitchTip | 前后端异常上报 | 按需,本地默认关闭 |
容器与端口
| 容器 | 镜像 | 端口映射 | 网络与挂载 |
|---|---|---|---|
asone-server | registry.cn-shenzhen.aliyuncs.com/qianxunclub/asone-server:latest | 127.0.0.1:8004->8001 | asone-net;/logs/asone-server:/logs、/data/asone-server/ip2region:/data/ip2region |
asone-front | .../qianxunclub/asone-front:latest | 127.0.0.1:8005->80 | bridge;/logs/asone-front:/var/log/nginx |
xxl-job-admin | .../qianxunclub/xxl-job-admin:latest | 127.0.0.1:8003->8080 | asone-net;/logs/xxl-job-admin:/data/applogs/xxl-job |
asone-net 是流水线创建的自定义网络,后端与调度中心互相以容器名直连(xxl.job.admin.addresses=http://xxl-job-admin:8080),避免绕公网域名回环被防火墙策略掐断注册心跳。
镜像构建
# 后端:mvn 打包 + 构建镜像
cd asone-server && ./build.sh
# 前端:max build 产出 dist/ + 构建镜像
cd asone-front && ./build.sh
| Dockerfile | 基础镜像 | 关键点 |
|---|---|---|
asone-server/Dockerfile | eclipse-temurin:25-jre-jammy | TZ=Asia/Shanghai、SPRING_PROFILES_ACTIVE=production、COPY asone-server-boot/target/*.jar、ENTRYPOINT java --enable-native-access=ALL-UNNAMED -jar /app/app.jar |
asone-front/Dockerfile | nginx:alpine | 内置 asone-front/nginx.conf,dist/ 拷到 /usr/share/nginx/html |
xxl-job/deploy/Dockerfile | eclipse-temurin:25-jre | 调度中心 jar 由流水线放入 xxl-job/deploy/xxl-job-admin.jar,配置走 SPRING_CONFIG_ADDITIONAL_LOCATION=file:/app/config/application.properties |
xxl-job/deploy/application.properties 保存调度中心的 MySQL 与 SMTP 外部配置,属部署物料,不在 xxl-job/xxl-job/ 上游源码范围内。
CI/CD 流水线(flow.yaml)
阿里云云效 Flow,源码 https://gitee.com/qianxunclub/asone.git 的 master,已开启 submodule。阶段顺序:
- 变更检测:
git log --name-only -1 HEAD判断本次提交是否触及asone-server/、asone-front/、xxl-job/,产出BACKEND_CHANGED/FRONTEND_CHANGED/XXLJOB_CHANGED并提升为流水线级变量,后续所有 job 用"<VAR>" == "true"条件跳过。改flow.yaml自身会让前后端都重跑。 - 构建和推送镜像(并行三个 job,各自挂失败邮件通知)
- 后端:SetupJava(JDK 25)+ Maven 3.9.3 →
cd asone-server && mvn -B clean package -DskipTests=true→ Docker Login 阿里云与轩辕镜像源 → 构建推送asone-server:latest(dockerfilePath: asone-server/Dockerfile,contextPathasone-server)。 - 前端:SetupNode 26.7.0 + pnpm →
pnpm install --frozen-lockfile+pnpm run build→ 构建推送asone-front:latest。 - 调度中心:在
xxl-job/xxl-job内mvn -pl xxl-job-admin -am后把 jar 拷到xxl-job/deploy/xxl-job-admin.jar→ 用xxl-job/deploy/Dockerfile构建推送xxl-job-admin:latest。
- 后端:SetupJava(JDK 25)+ Maven 3.9.3 →
- 部署:
VMDockerDeploy组件 + 机器组,pauseStrategy: firstBatchPause、batchNumber: 2,按上面的变更标记分别docker pull+docker run(命令见「容器与端口」表)。 - 部署结果校验:
sleep 20后轮询健康检查,任一项在重试耗尽前没有"status":"UP"就exit 1判失败:- 后端
https://asone.club/actuator/health(15 次 × 20s) - 前端
https://asone.club/healthz(10 次) - 调度中心
https://xxl-job-admin.asone.club/actuator/health(10 次)
- 后端
- 清理旧镜像:
docker system df→docker image prune -f。
上线顺序与配置
- DDL 先于代码:任何新增列(例如
system_resource.role_scope、icon)必须先在目标库执行,再发后端版本,否则资源查询因缺列失败。 - 后端配置分层:
application.yml(默认,profiles.include=system,channel-report)+ 模块application-xxx.yml;生产以SPRING_PROFILES_ACTIVE=production生效,敏感值通过环境变量或部署平台外部配置注入。 - 上线前逐项确认:
spring.profiles.active、MySQL / Redis 连接、xxl.job.admin.addresses与执行器access-token(必须与调度中心asone-server分组注册 Token 完全一致,3.x 起为空会注册失败)、对象存储与验证码配置、spring.messages.basename是否包含新增模块的 bundle。 - 优雅停机:生产
server.shutdown=graceful,timeout-per-shutdown-phase=300s,长任务与 SSE 有充足收尾时间;本地为immediate。 - 后端日志落容器内
/logs(映射到宿主/logs/asone-server), XXL-JOB 执行日志落/data/applogs/xxl-job。
部署后验证
# 前端页面
curl -sS -o /dev/null -w "asone.club http_code=%{http_code}\n" https://asone.club/
# 后端接口链路:返回验证码相关错误即证明 OpenResty -> asone-server 通畅
curl -sS -X POST https://asone.club/api/auth/login \
-H "Content-Type: application/json" \
-d '{"account":"<账号>","password":"<口令>","captchaVerifyParam":"test"}'
# 鉴权拦截:未带 token 应返回 401
curl -sS -o /dev/null -w "http_code=%{http_code}\n" https://asone.club/api/system/admin/page
# 健康检查
curl -sS https://asone.club/actuator/health
curl -sS https://asone.club/healthz
后台登录要求阿里云验证码,命中非信任设备还会走邮箱 / 短信两步验证,所以登录只能在浏览器里人工完成;curl 能验证到「接口通了、参数被正确校验」这一层。服务器与容器状态、磁盘内存等排错命令见 .trae/rules/deployment.md。
配置与密钥的已知偏差
asone-server-boot/src/main/resources/application.yml 目前直接写有生产数据源、Redis 与 SMTP 的口令,与「敏感值通过环境变量注入」的约定不一致。后续应改为占位符 + 环境变量(${SPRING_DATASOURCE_PASSWORD} 形式)并由部署平台下发,历史提交中的凭据需轮换。在此之前,任何文档、截图与提交信息都不得复制这些值。
