Files
fangke/deploy/README-deploy.md
T
2026-09-15 21:32:20 +08:00

129 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 部署指南(1Panel + Docker Compose)
面向 1Panel 用户的生产部署。产物为 `docker compose` 两个服务:`web`(Django + gunicorn)与 `nginx`(admin SPA / SDK 静态 + API 反代),数据库复用 1Panel 已装的 MySQL。
## 1. 前置构建(仓库内完成,产出 dist 与 xdb)
```bash
# 管理后台:产出 admin/dist/
cd admin && pnpm install && pnpm build && cd ..
# 采集 SDK:产出 sdk/dist/v1.js
cd sdk && pnpm install && pnpm build && cd ..
```
下载 ip2region 离线库到 `deploy/data/ip2region.xdb`(compose 以只读卷挂载进容器,重建容器不丢):
- GitHub:https://github.com/lionsoul2014/ip2region (`data/ip2region_v4.xdb`)
- 大陆备用:https://gitee.com/lionsoul/ip2region (同名路径)
```bash
mkdir -p deploy/data
cp /path/to/ip2region_v4.xdb deploy/data/ip2region.xdb
```
## 2. MySQL 准备(1Panel 已有容器)
在 1Panel 的 MySQL 里建库建账号(utf8mb4):
```sql
CREATE DATABASE tracker CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'tracker'@'%' IDENTIFIED BY '<强密码>';
GRANT ALL PRIVILEGES ON tracker.* TO 'tracker'@'%';
FLUSH PRIVILEGES;
```
**容器连宿主 MySQL 的三条路径**(`.env` 的 `DB_HOST` 三选一):
| 路径 | 做法 | DB_HOST | 备注 |
|---|---|---|---|
| a | 走宿主机发布端口(compose 已配 `extra_hosts: host.docker.internal:host-gateway`) | `host.docker.internal` | MySQL 端口需以 `0.0.0.0` 发布(1Panel 默认如此),账号 host 为 `%` |
| b **推荐** | compose 追加外部网络,与 MySQL 容器同网 | `<MySQL 容器名>`(如 `1Panel-mysql-xxxx`) | 不暴露额外端口,容器名在 1Panel 容器列表可见 |
| c | 走 docker0 网桥网关 | `172.17.0.1` | 网桥地址随环境可能变化,兜底用 |
路径 b 的 compose 改法(文件末尾已有注释模板,取消注释即生效):
```yaml
networks:
default:
name: 1panel-network
external: true
```
## 3. 配置 .env
```bash
cd deploy
cp .env.example .env
```
填必填项:`DJANGO_SECRET_KEY`(生成命令见文件内注释)、`DJANGO_ALLOWED_HOSTS`(实际域名)、`DB_*`。
**fail-fast 设计**:`DJANGO_ENV=prod` 时缺 `SECRET_KEY` / `ALLOWED_HOSTS` 启动即崩(`RuntimeError`),不带病上线——这是有意为之的护栏,不是 bug。漏配时看容器日志 `docker compose logs web` 即可定位。
## 4. 部署
```bash
docker compose up -d --build
# 建管理员账号(JWT 登录用)
docker compose exec web python manage.py createsuperuser
```
浏览器访问 `http://<服务器IP>/`(有域名先做第 5 步 HTTPS)。
## 5. HTTPS(1Panel 二选一)
- **做法一(推荐)**:1Panel「网站」→ 创建网站 → 反向代理到 `http://127.0.0.1:80`,在网站设置里申请 Let's Encrypt 证书并开启 HTTPS。本 compose 的 nginx 只听 80,TLS 由 1Panel 的 OpenResty 终结。
- **做法二**:域名 DNS 直接解析到服务器,1Panel「网站」创建站点直接挂证书(证书路径填入 1Panel 证书管理),也能达到同样效果。
任选其一即可,务实为准。HTTPS 后 SDK endpoint 与后台访问地址同步换成 `https://`。
## 6. 建站点拿 site_id
登录后台 → 站点管理 → 新建站点(填域名) → 列表里复制 `site_id`(形如 `site_xxxxxxxx`),接入目标网站时用它。
## 7. 目标网站接入
目标站 `<head>` 里加两行(endpoint 与 SDK 地址换成正式域名):
```html
<script>window.ctk = window.ctk || function(){(ctk.q=ctk.q||[]).push(arguments)};
ctk("init", { siteId: "<上一步的 site_id>", endpoint: "https://track.example.com/api/collect/batch" });</script>
<script async src="https://track.example.com/sdk/v1.js"></script>
```
## 8. 定时任务(不做则趋势图历史全零)
1Panel「计划任务」→ 每日 00:10 执行(Shell 脚本):
```bash
docker exec tracker-web python manage.py refresh_stats --days 2
```
`refresh_stats` 聚合昨日明细为每日统计快照(`--days 2` 幂等重算近两天,补齐漏跑)。
## 9. JWT 应急
token 泄露时**唯一**吊销手段是更换 `DJANGO_SECRET_KEY`(JWT 由它签名,换钥即全体登出):重新生成 → 改 `.env` → `docker compose up -d`。后台没有"注销某 token"的接口,这是无状态 JWT 的设计取舍。
## 10. CDN / WAF 注意
目标网站套 CDN/WAF 后,到达采集 API 的 `X-Forwarded-For` 层数会变化(CDN 一层 + 本站 nginx 一层 = 2 层起)。取真实客户端 IP 依赖 DRF `NUM_PROXIES`(当前为 1,对应"仅前置一层可信代理"取末段)。CDN 层数变化后需同步调整 `server/config/settings.py` 的 `NUM_PROXIES` 并重建镜像,否则取到的是 CDN 节点 IP,地域与去重统计失真。
## 11. 大陆网络备用源
| 资源 | 主源 | 备用源 |
|---|---|---|
| admin 模板(Vite 等 npm 依赖) | npm registry | `pnpm config set registry https://registry.npmmirror.com` |
| ip2region xdb | GitHub lionsoul2014/ip2region | gitee.com/lionsoul/ip2region |
| pip 依赖 | pypi.org | 清华源(**Dockerfile 已内置** `-i https://pypi.tuna.tsinghua.edu.cn/simple`) |
---
### 附:常用运维命令
```bash
docker compose logs -f web # 看后端日志
docker compose up -d --build # 改代码后重建
docker compose exec web python manage.py createsuperuser # 再建账号
```