From ce4ff74b7d74712d7b7b04d0005a60018890a5c2 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 19 May 2026 12:37:49 +0800 Subject: [PATCH] chore: add production docker smoke check --- RULES.md | 1 + docs/source-analysis.html | 14 +++++++++++++- scripts/verify-prod-docker.sh | 29 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100755 scripts/verify-prod-docker.sh diff --git a/RULES.md b/RULES.md index c48be5e..45ebd37 100644 --- a/RULES.md +++ b/RULES.md @@ -24,6 +24,7 @@ - 服务器目录:`/opt/skg-marketing-studio` - 生产启动:`docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -d --build` - 生产架构:`web` 容器用 Nginx 承载 Next 静态导出;`/login/`、`/_next/`、`/assets/`、`/skg-logo-black.svg`、`/oasis-source/` 等登录页必需静态资源公开访问;未登录访问工作台跳转 `/login/`,`/api/` 通过 Nginx `auth_request` 校验 FastAPI 会话 Cookie 后反代到 `skg-marketing-api:4291`;Traefik 通过 `coolify` 外部网络接入 80/443 +- Web 验收必须以生产 Docker 形态为准:前端是 `next export` 静态产物 + Nginx,不是 `next dev` / `next start`。任何 Web 改动部署后必须运行 `./scripts/verify-prod-docker.sh`,确认 `/login/`、`/_next/`、`/api/health`、本地 API 地址泄漏和 API 镜像 `.env` 污染检查通过;不能只用本地 `npm run build` 作为上线依据。 - 持久化目录:服务器 `./data/jobs` 挂载到后端 `/data/jobs`;全局资源中心持久化在 `./data/asset_library`、`./data/prompt_library` 和 `./data/_trash` - TikTok 下载登录态:公开视频默认不带 cookies 直接下载,生产环境变量必须显式保持 `YTDLP_COOKIES_FILE=`、`YTDLP_COOKIES_FROM_BROWSER=` 为空,防止容器读取不存在的浏览器 cookies。只有 TikTok 明确要求登录态时,才使用服务器私有 cookies 文件 `./secrets/tiktok_cookies.txt` 挂载到 API 容器 `/run/secrets/tiktok_cookies.txt` 并配置 `YTDLP_COOKIES_FILE=/run/secrets/tiktok_cookies.txt`;`yt-dlp` 会在任务结束时回写 cookies,因此不要把该挂载设为只读;不要使用云端浏览器读取方案,也不要把 cookies 入库。生产容器严禁使用 `YTDLP_COOKIES_FROM_BROWSER=chrome`。 - 登录凭证:用户名写下方快捷登录;密码明文备份只放服务器 `/root/skg-marketing-studio-login.txt`,生产环境变量 `WEB_AUTH_PASSWORD` / `WEB_AUTH_SESSION_SECRET` 只放服务器 `deploy/.env.production` diff --git a/docs/source-analysis.html b/docs/source-analysis.html index f924cd4..39d5636 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -541,7 +541,7 @@ 生产部署 docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -d --build - 服务器目录为 /opt/skg-marketing-studio;后端任务文件挂载到 ./data/jobs,全局资源中心挂载到 ./data/asset_library./data/prompt_library./data/_trash,真实 Key 只放服务器 deploy/.env.production。 + 服务器目录为 /opt/skg-marketing-studio;后端任务文件挂载到 ./data/jobs,全局资源中心挂载到 ./data/asset_library./data/prompt_library./data/_trash,真实 Key 只放服务器 deploy/.env.production。Web 上线验收必须按 Docker 静态形态跑 ./scripts/verify-prod-docker.sh,不能只用本地 npm run build 替代。 前端开发服务 @@ -1108,6 +1108,18 @@ ProductRefStateItem {

变更记录

这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。

+
+
+

2026-05-19 · 固化生产 Docker Web 验收

+ Deploy + UI +
+
+

问题:线上 Web 不是开发态 Next 服务,而是 Docker 内 Nginx 承载的 next export 静态产物。只在本地跑 npm run build 或 dev server,无法覆盖 Nginx 登录跳转、/api 反代、静态资源路径、生产构建参数和镜像内环境污染。

+

改动:新增 scripts/verify-prod-docker.sh,直接在 VPS 的 skg-marketing-web / skg-marketing-api 容器内检查路由状态、静态包是否残留本地 API 地址、API health、/app/.env 是否泄漏,以及 yt-dlp cookies 参数是否被开发环境污染。RULES.md 明确 Web 改动部署后必须跑该脚本。

+

影响:后续前端上线验收以生产 Docker 形态为准;本地 dev 只用于开发预览,不能作为生产适配结论。

+
+

2026-05-19 · 修正生产 TikTok 下载 cookies 污染

diff --git a/scripts/verify-prod-docker.sh b/scripts/verify-prod-docker.sh new file mode 100755 index 0000000..7c35610 --- /dev/null +++ b/scripts/verify-prod-docker.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +HOST="${1:-root@76.13.31.179}" +APP_DIR="${APP_DIR:-/opt/skg-marketing-studio}" + +ssh "$HOST" "cd '$APP_DIR' && \ + docker ps --filter name=skg-marketing --format '{{.Names}} {{.Status}}' && \ + docker exec skg-marketing-web sh -lc ' + set -e + echo web:no_local_api_refs + if grep -Rao \"http://localhost:4291\\|http://127.0.0.1:4291\\|localhost:4290\\|127.0.0.1:4290\" /usr/share/nginx/html/_next/static 2>/dev/null | head -1 | grep -q .; then + echo \"ERROR: local API/dev URL leaked into web static bundle\" >&2 + exit 1 + fi + for p in / /login/ /_next/does-not-exist.js /api/health; do + code=\$(curl -sS -o /tmp/skg-smoke.out -w \"%{http_code}\" \"http://127.0.0.1\$p\") + case \"\$p:\$code\" in + /:302|/login/:200|/_next/does-not-exist.js:404|/api/health:401) echo \"web:\$p \$code\" ;; + *) echo \"ERROR: unexpected web route status \$p \$code\" >&2; head -c 200 /tmp/skg-smoke.out >&2; exit 1 ;; + esac + done + ' && \ + docker exec skg-marketing-api sh -lc ' + set -e + test ! -f /app/.env || { echo \"ERROR: /app/.env leaked into API image\" >&2; exit 1; } + python -c \"import main; assert main.YTDLP_COOKIES_FROM_BROWSER == \\\"\\\", main.YTDLP_COOKIES_FROM_BROWSER; print(\\\"api:ytdlp_cookie_args\\\", main.ytdlp_cookie_args())\" + curl -sS http://127.0.0.1:4291/health | python -c \"import json,sys; d=json.load(sys.stdin); assert d[\\\"ok\\\"] is True; assert d[\\\"auth_configured\\\"] is True; print(\\\"api:health ok\\\")\" + '"