feat(deploy): D1 后端部署就绪(配置外置 + prod fail-fast + 自包含 Compose + 冒烟/回滚)

为什么:用户下午要部署,但全仓没有任何部署产物;且生产漏配密钥会静默使用代码里的 dev 默认值,
属上线阻塞项(04-部署架构 / 12-上线检查清单)。

- 配置外置(三件):DB_URL、JWT 双密钥(**发现 app-secret 此前没外置,一直用 dev 默认值**)、
  MEDIA_SIGNATURE_SECRET、MEDIA_SIGNATURE_REQUIRED、CORS_ALLOWED_ORIGINS、MEDIA_ROOT_DIR
- 新增三份 application-prod.yml:签名强制开启、CORS 收紧、媒资指向挂载点、日志级别
- 新增 ProdSecretGuard(@Profile("prod")):密钥缺失/仍是 dev 默认值/不足 32 位、签名未开、
  DB_URL 或 CORS 为空 → 一次列全并终止启动(exit 1)
- 新增 /healthz 轻量健康端点:查明 /actuator/health 的"超时"是旧 jar 未重启所致,项目本就
  没有 actuator 依赖,故不引新依赖;同时把 /healthz 加进安全白名单
- Docker 化:多阶段 Dockerfile(非 root、tini、依赖层缓存、ffmpeg 只给 worker)、.dockerignore、
  自包含 docker-compose.yml(含 PostgreSQL 18 + Redis + 命名卷 + 按序初始化 sql + healthcheck)
- tools/smoke.sh(失败非 0 退出)+ DEPLOY.md(Compose 主线 / 裸 jar 兜底 / 回滚 / 故障速查)
- 实测:mvn test 83 条全过;两入口 package 通过;prod 缺密钥退出码 1 且报错明确、配齐后正常启动;
  冒烟脚本全 PASS;本机无 Docker,镜像与 compose 未经构建验证(已在回执如实标注)
This commit is contained in:
jianghaifeng committed 2026-10-16 13:01:08 +08:00
1 parent 9f76302e53
commit b567365460
16 files changed
+814 -9

No files matched your search

@@ -0,0 +1,24 @@
# Author: fruit.com.cn
#
# 生产 profile:worker 只消费队列,不对外提供接口。
# 密钥校验(JWT / 媒体签名)由 ProdSecretGuard 统一 fail-fast —— worker 也要求密钥齐全,
# 这样"生产漏配密钥"不会表现为"worker 能起但入口起不来"这种半吊子状态。
server:
port: 0
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
fruitshorts:
media:
transcode:
# 生产此进程必须真的跑转码
worker-enabled: true
# 生产按小时级重试间隔,避免坏片源把队列打满
poll-delay-ms: ${TRANSCODE_POLL_DELAY_MS:5000}
logging:
level:
root: info
com.fruitshorts: info
@@ -12,7 +12,8 @@ spring:
exclude: org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:5432/fruitshorts
# 与两个入口同一个库(worker 消费 transcode_task)
url: ${DB_URL:jdbc:postgresql://127.0.0.1:5432/fruitshorts}
username: ${DB_USER:fruitshorts}
password: ${DB_PASSWORD:fruitshorts}
@@ -35,7 +36,7 @@ mybatis-plus:
fruitshorts:
media:
# 必须与 app-api/admin-api 指向同一个存储根,worker 才找得到上传后的源文件
root-dir: ./data/uploads
root-dir: ${MEDIA_ROOT_DIR:./data/uploads}
public-prefix: /files
transcode:
# 只有本进程打开转码(§8.5 隔离要求)