# 生产部署说明 目标访问地址: ```text https://主站域名 # CADDY_DOMAIN,哈夫币系统 https://选号网域名 # CADDY_SHOW_DOMAIN(可选),hfb_show 静态选号站 https://monitor.主站域名 # Beszel 监控 ``` 生产部署使用 Caddy 作为公网入口,只暴露宿主机 `80`、`443` 端口。Caddy 会自动申请和续签 HTTPS 证书,并直接托管前端静态资源(主站 `dist` 与可选的选号网 `show-dist` 在构建 Caddy 镜像时打入);后端、MySQL、Redis、MinIO 均通过 Docker 内网通信。选号网与主站**共用同一 backend**,浏览器访问选号网域名下的 `/api/*` 由 Caddy 反代到本机 backend,**不会直连数据库**。 部署前请确认: - 主站域名 A 记录已解析到服务器公网 IP;启用选号网时,选号网域名也要解析到同一 IP。 - 服务器安全组或防火墙已放行 `80/tcp` 和 `443/tcp`。 - 服务器上没有其他服务占用 `80`、`443`。 - 国内服务器如需对外访问,请先确认域名备案和云厂商限制。 ## 1. 准备环境变量 ```bash cp backend/.env.prod.example backend/.env ``` 编辑 `backend/.env`,至少替换以下占位值: ```text CADDY_DOMAIN CADDY_EMAIL MYSQL_ROOT_PASSWORD MYSQL_PASSWORD MYSQL_DSN JWT_SECRET MINIO_ROOT_USER MINIO_ROOT_PASSWORD STORAGE_ACCESS_KEY_ID STORAGE_SECRET_ACCESS_KEY ``` ### 同机部署选号网(hfb_show,可选) 在 `backend/.env` 增加(域名不要带 `https://`): ```text CADDY_SHOW_DOMAIN=show.example.com HFB_SHOW_DIR=../hfb_show ``` 要求: 1. 服务器上 `hfb_show` 与 `hfb_sys` 同级目录(或 `HFB_SHOW_DIR` 指向真实路径)。 2. 部署机可执行 `npm`(脚本会在 build Caddy 前构建选号网 dist)。 3. 选号网域名 DNS 已指向本机。 一键脚本会自动: - `npm ci && npm run build` 选号网; - 将 `dist` 同步到 `deploy/caddy/show-dist`; - 生成 Caddy 站点配置 `deploy/caddy/conf.d/show.caddy`; - 构建 Caddy 镜像时打入主站 + 选号网静态资源; - 为选号网域名申请 HTTPS,并把 `/api/*` 反代到 `backend:8080`。 不配置 `CADDY_SHOW_DOMAIN` 则行为与原来一致,仅部署主站。 如果正式对外运营,还需要配置真实短信和实名服务,避免继续使用测试配置。 ## 2. 一键部署 ```bash ./scripts/deploy-prod.sh ``` 脚本会自动完成: - 检查 `backend/.env` 是否仍指向 `127.0.0.1`、`localhost` 或占位值。 - 使用内置 MinIO 时,检查 `STORAGE_ACCESS_KEY_ID` / `STORAGE_SECRET_ACCESS_KEY` 是否和 `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD` 一致。 - 构建并启动生产容器。 - 通过 Caddy 自动申请或续签 HTTPS 证书。 - 等待 MySQL、Redis、MinIO 就绪。 - 按顺序执行尚未应用的数据库迁移。 - 重启后端并检查 `https://你的域名/api/health`。 如需部署完成后直接跟随查看后端日志: ```bash ./scripts/deploy-prod.sh --logs ``` 后端运行日志会同时输出到 Docker 控制台,并写入宿主机: ```text backend/logs/app-YYYY-MM-DD.log ``` 测试阶段需要清空并重建数据库时: ```bash ./scripts/deploy-prod.sh --reset-db ``` ## 3. 手动启动服务 ```bash set -a source backend/.env set +a docker compose -f deploy/docker-compose.prod.yml up -d --build ``` 手动执行 `docker compose` 时需要先导出 `CADDY_DOMAIN` 和 `CADDY_EMAIL`,否则 Caddy 无法读取证书域名配置。优先推荐使用一键部署脚本,它会自动从 `backend/.env` 导出这两个变量。 ## 4. 手动执行数据库迁移 通常直接使用一键部署脚本即可。确实需要手动迁移时,使用后端镜像内置的 goose: ```bash MYSQL_DSN="$(awk -F= '$1=="MYSQL_DSN"{sub(/^[^=]*=/,""); print; exit}' backend/.env)" case "$MYSQL_DSN" in *multiStatements=*) GOOSE_DSN="$MYSQL_DSN" ;; *\?*) GOOSE_DSN="${MYSQL_DSN}&multiStatements=true" ;; *) GOOSE_DSN="${MYSQL_DSN}?multiStatements=true" ;; esac docker compose -f deploy/docker-compose.prod.yml run --rm --no-deps backend \ /app/goose -dir /app/migrations mysql "$GOOSE_DSN" up ``` ## 5. 验证 ```bash curl https://主站域名/health curl https://主站域名/api/health # 若启用了选号网: curl -I https://选号网域名/ curl https://选号网域名/api/health curl "https://选号网域名/api/listings?page=1&page_size=1" ``` 浏览器访问: ```text https://主站域名 https://主站域名/你配置的后台入口/login https://选号网域名 # 选号网首页 ``` Caddy 证书和 ACME 账号数据保存在 Docker 卷 `caddy_data`、`caddy_config` 中。不要随意删除这两个卷,否则 Caddy 会重新申请证书,频繁重建可能触发证书签发频率限制。