56 lines
4.7 KiB
Markdown
56 lines
4.7 KiB
Markdown
# dealerhub · 生产部署 Readiness Gate 清单(P2-2)
|
||
|
||
> 状态:**本地校验通过,未实际部署**。唯一会碰生产动作的项(镜像构建/上线
|
||
> 192.168.5.7)因无服务器凭证,停在"清单 + 本地校验",不伪造部署成功。
|
||
> 验证环境:Windows + Docker 29.7.2 + Python 3.12.10,2026-09-12 实跑。
|
||
|
||
## 一、本地校验(已跑通,exit 0)
|
||
|
||
| # | 项 | 命令 | 结果 |
|
||
|---|---|---|---|
|
||
| 1 | compose 插值 | `DJANGO_SECRET_KEY='x' POSTGRES_PASSWORD='x' docker compose -f backend/infra/docker/docker-compose.yml config` | ✅ exit 0,`DATABASE_URL`/`SECRET_KEY`/`POSTGRES_PASSWORD` 均已插值,无 `required` 残留告警 |
|
||
| 2 | prod check | `DJANGO_SETTINGS_MODULE=config.settings.prod DJANGO_SECRET_KEY=dummy DJANGO_ALLOWED_HOSTS=example.com DATABASE_URL=postgres://u:p@localhost:5432/db python manage.py check` | ✅ `System check identified no issues (0 silenced)` |
|
||
| 3 | collectstatic | 同上环境 `python manage.py collectstatic --noinput`(实跑非 dry-run,写 `backend/staticfiles/`) | ✅ `216 static files copied` |
|
||
| 4 | ALLOWED_HOSTS 空值门 | 不传 `DJANGO_ALLOWED_HOSTS`(仅继承 dev `.env` 的 `*`)→ `manage.py check` | ✅ 被拒:`生产环境不允许 DJANGO_ALLOWED_HOSTS 含通配符 '*'`(本次新增,见 §三) |
|
||
| 5 | ALLOWED_HOSTS 显式域名 | `DJANGO_ALLOWED_HOSTS=example.com` → `manage.py check` | ✅ 0 issues |
|
||
| 6 | prod 安全基线 | 同环境打印 settings | ✅ `DEBUG=False`;`dealerhub` logger `INFO`;PG `pool min2/max10/timeout10`;HSTS `2592000+include+preload`;`SESSION/CSRF_COOKIE_SECURE=True`;`SECURE_PROXY_SSL_HEADER=https`;`X_FRAME_OPTIONS=DENY` |
|
||
| 7 | DB 方言 | prod `ENGINE=django.db.backends.postgresql` | ✅ 非 SQLite(SQLite 不适合生产并发,见 NEXT_PLAN P1-1) |
|
||
|
||
## 二、上线 192.168.5.7 前的 Gate(逐项打勾才能上)
|
||
|
||
- [ ] **环境变量**:目标机上设置 `DJANGO_SECRET_KEY`(≥32 随机)、`POSTGRES_PASSWORD`、
|
||
`DJANGO_ALLOWED_HOSTS=实际域名`(逗号分隔,禁 `*`)、`DATABASE_URL`(PG)。
|
||
参考:` §一#1` 的插值校验。
|
||
- [ ] **镜像构建**:`docker compose -f backend/infra/docker/docker-compose.yml build backend`
|
||
(Node+Python 多阶段,镜像内 `npm ci && npm run build`,不依赖宿主 `dist/`)。
|
||
- [ ] **迁移**:容器启动脚本 `infra/scripts/run_prod_granian.sh` 自动
|
||
`python manage.py migrate --noinput`;上线后用 `manage.py showmigrations` 抽查无未应用迁移。
|
||
- [ ] **collectstatic**:同脚本自动 `collectstatic --noinput`;用 `curl /static/` 抽查 200。
|
||
- [ ] **`DJANGO_DEBUG=False`**:prod 已硬编码 `DEBUG=False`(`config/settings/prod.py`),
|
||
用 §一#6 命令复验。
|
||
- [ ] **PG 已切**:`DATABASE_URL` 指向生产 PG(本机 PG 5433 仅用于并发测试,不可当生产库)。
|
||
- [ ] **HTTPS**:`SECURE_PROXY_SSL_HEADER + HSTS + Secure Cookie` 已配(§一#6),
|
||
前置反代(1Panel/nginx)必须透传 `X-Forwarded-Proto: https` 并配证书;`curl -I https://域名` 验 HSTS 头。
|
||
- [ ] **日志轮转**:应用层只打 console(`StreamHandler`,无文件 handler,见 §四);
|
||
靠宿主 `docker logs --log-opt max-size/max-file` 或 journald 做轮转,**不要**在容器内写日志文件。
|
||
- [ ] **备份**:PG 每日 `pg_dump`(或卷快照)+ 留存 ≥7 天,恢复演练每季度一次。
|
||
现状:仓库内无备份脚本(§四),上线前由运维侧补齐,本清单不虚构。
|
||
- [ ] **冒烟**:`GET /api/v1/ping/` → 登录 → 开单,三接口 200(D2 移动端同链路已在本地验证,见 `backend/scripts/verify_salesman_h5.py`)。
|
||
|
||
## 三、本轮修补(P2-2 附带真缺口)
|
||
|
||
`prod.py` 的 ALLOWED_HOSTS 空值门可被 dev `.env`(`DJANGO_ALLOWED_HOSTS=*`,
|
||
经 `base.py:read_env` 写进 `os.environ`)绕过:不传变量时读到 `*` 而非空,
|
||
门禁静默通过,生产接受任意 Host。修法:显式拒绝通配符(`backend/config/settings/prod.py`),
|
||
验证见 §一#4/#5。无测试依赖 prod 通配符(全仓 grep `settings.prod` 零命中)。
|
||
|
||
## 四、诚实记录(未做,不虚报)
|
||
|
||
1. **镜像构建未跑**:需 Docker daemon 完整构建上下文(含 `npm ci` 拉包),
|
||
本机 `docker compose config` 仅做插值校验(§一#1),`build/up` 留待目标机。
|
||
2. **未上线 192.168.5.7**:无服务器凭证,`up -d` 与三接口冒烟留待部署时按 §二执行。
|
||
3. **日志轮转/备份无代码交付**:现状应用层无文件日志、无备份脚本,
|
||
§二对应项为运维动作,仓库不伪造实现。
|
||
4. **P3-1 行业专版跳过**:按 NEXT_PLAN P3-1/D3 定调"按客户驱动,不提前做",
|
||
本轮未建 `Serial`/辅助属性/套装拆件,grep 仍零命中即为预期状态。
|