# 部署与 CI/CD 说明 项目结构:前端 Astro 静态站 + 后端 Go 服务 + MySQL。采用 **Docker 容器化 + Gitea Actions** 上线。 ## 一、架构 ``` 浏览器 │ HTTP (80) ▼ [frontend] nginx:80 ── 静态资源 / , 反代 /api ──▶ [backend] Go :8090 │ ▼ [db] MySQL 8.0 ``` - **前端**:Astro 构建为静态 `dist/`,用 nginx 托管;`/api` 由 nginx 反代到 `backend:8090`(同源,无跨域)。 - **后端**:Go 二进制,监听 `8090`,连 `db` 服务。 - **构建期 SSR**:`brands.astro` 在构建时拉数据,地址用 `API_SSR`(容器内部 `http://localhost:8090`,配合 `build.network: host` 访问已启动的 backend 容器);运行期浏览器走同源 `/api`。 ## 二、服务器目录约定 ```bash /opt/fashion/ ├── test/ # 前端仓 git clone(含 docker-compose.yml / deploy.sh / Dockerfile / nginx.conf) └── admin/ └── backend/ # 后端仓 git clone(含 Dockerfile) ``` 初始化(在服务器上): ```bash mkdir -p /opt/fashion && cd /opt/fashion git clone <前端仓地址> test git clone <后端仓地址> admin/backend cd test cp .env.example .env # 按需修改 JWT_SECRET / DB_PASSWORD ``` 前置:服务器已安装 Docker Engine + Docker Compose v2,且当前用户可免 sudo 执行 docker。 ## 三、手动一键上线 在服务器上(或本地 SSH 过去)执行: ```bash cd /opt/fashion/test ./deploy.sh ``` `deploy.sh` 会:① 拉两个仓库最新代码 → ② `docker compose up -d db backend` → ③ 轮询等待 backend 健康 → ④ `docker compose build frontend`(构建期 SSR 拉数据)→ ⑤ `docker compose up -d frontend`。 完成后访问服务器 `http://<服务器IP>/` 即可。 ## 四、CI/CD(Gitea Actions) 仓库根已放入 `.gitea/workflows/deploy.yml`。push 到 `main`/`master` 即自动 SSH 到服务器执行 `./deploy.sh`。 前置(Gitea 仓库 → Settings → Secrets / Actions): | Secret | 说明 | | ------------- | ---------------------------- | | `DEPLOY_HOST` | 服务器 IP / 域名 | | `DEPLOY_USER` | SSH 用户名 | | `DEPLOY_KEY` | 服务器私钥(对应公钥已放入 `~/.ssh/authorized_keys`) | > 后端仓库也放一份相同的 `.gitea/workflows/deploy.yml`,这样前后端任意仓库 push 都会触发一次完整上线(deploy.sh 会同时 pull 两个仓)。 ## 五、HTTPS(可选) 在服务器前置一个反向代理(如 Caddy / 已有 nginx)终止 TLS,把 80 转发到 frontend 容器,并加 `X-Forwarded-Proto`。或把 frontend 的 `ports` 换成 `443` + 挂载证书。此处从简,未内置。 ## 六、注意事项 - 后端环境变量名(`DB_HOST`/`JWT_SECRET` 等)需与实际 `config` 读取一致;如后端用别的变量名,改 `docker-compose.yml` 的 `environment` 即可。 - `JWT_SECRET` 生产务必改成随机长串;默认值是占位的。 - 生产可去掉 `backend.ports` 的 `8090:8090` 暴露,仅由前端 nginx 在同一 compose 网络内反代访问,更安全。 - 前端 `PUBLIC_API_BASE` 在 Dockerfile 中置空(同源 `/api`);如需独立域名,改为绝对地址并在后端已开启 CORS(`*`)。