From 0d2a954153d95c3afd4d13ad4274b052e4c5a29a Mon Sep 17 00:00:00 2001 From: yeuimu <2197651308@qq.com> Date: Thu, 3 Sep 2026 02:09:24 +0800 Subject: [PATCH] =?UTF-8?q?deploy(single-stack):=20=E5=8D=95=E6=A0=88?= =?UTF-8?q?=E6=94=B6=E6=95=9B=E2=80=94=E2=80=94v2=20=E5=B9=B6=E5=85=A5=20d?= =?UTF-8?q?eploy=20compose=EF=BC=8Cv1=20=E9=80=80=E5=BD=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docker-compose.yml 重写为单栈 4 容器(admin 边缘 + v2-api/v2-admin/v2-postgres), v2 数据卷 deploy-v2_pgdata/uploads 以 external 引用,数据零迁移 - nginx:/uploads/ /assets/ 上游改 v2-api(product-center 覆盖块随之冗余移除), / 跳转 /v2/admin/;docker-compose.v2.yml 删除(血统已并入 develop) - v1 api+postgres 已停用未删,终档/快照/回滚手册见 deploy/backups/consolidation-*/ - 切换验证:v2 库切换前后行数完全一致;/v2-api /public /v2/admin /v2/h5 /assets 全路由冒烟 + 公网端到端通过 --- AGENTS.md | 2 + deploy/docker-compose.v2.yml | 75 ------------------------------------ deploy/docker-compose.yml | 58 +++++++++++++++++----------- deploy/nginx/admin.conf | 13 ++----- docs/references/structs.md | 12 ++++++ 5 files changed, 52 insertions(+), 108 deletions(-) delete mode 100644 deploy/docker-compose.v2.yml diff --git a/AGENTS.md b/AGENTS.md index 0405870..f8d8181 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -111,3 +111,5 @@ Prisma Postgres 最佳实践: prisma-postgres 技能 - **共享开发库不可达时用一次性 docker postgres 跑集成测试**:`docker run -d --name inkreach-test-pg -e POSTGRES_USER=test -e POSTGRES_PASSWORD=test -e POSTGRES_DB=inkreach_test -p 127.0.0.1:54329:5432 postgres:16-alpine` → `DATABASE_URL=… npx prisma migrate deploy` → jest/vitest 指向该库;用完 `docker rm -f`。夹具自包含的套件在新库上直接绿。 - **宿主机即部署机时,改生产数据前先 `docker inspect` 拿容器真实注入的环境变量**:deploy/.env 里的密码可能与运行容器不一致(v2 栈独立 env);对两个栈的库做数据修复时,dry-run 清单必须逐栈分别核对后再 apply。 - **改"镜像字段"的数据前先查覆盖路径**:分类名每小时被 `syncCategories` 用 SDS 原名无条件覆盖——直接改库/界面改名都会被下一轮同步冲回。此类字段的清洗必须写进同步入库路径(如 `cleanCategoryDisplayName`),存量靠回填脚本;数据先改而镜像未重部署的窗口期内会被冲回一次,重部署后自动恢复。 +- **合并分叉血统时警惕"文本无冲突、行为有冲突"**:git 自动合并可能把两侧对同一机制的不同设计(如 热转印=烫画别名 vs 一等公民词表)拼进一个文件,编译通过但行为矛盾——合并后必须跑两侧血统各自的测试才能暴露;行级冲突反而不是最危险的。另:`git status | head` 截断会漏看冲突文件,连续 cherry-pick 后要全仓 `grep '<<<<<<<'` 扫一遍。 +- **生产栈收敛三件套**:动栈结构前先 `pg_dump -Fc` 双库 + 数据卷归档 + 配置快照落 `deploy/backups/<时间戳>/` 并写 RESTORE.md;切换用"外部卷 external 引用 + down 不带 -v + 切换前后行数 diff"保证数据零丢失;先 `docker compose build` 预构建再 down/up,把停机窗口压到秒级。 diff --git a/deploy/docker-compose.v2.yml b/deploy/docker-compose.v2.yml deleted file mode 100644 index 1bf6453..0000000 --- a/deploy/docker-compose.v2.yml +++ /dev/null @@ -1,75 +0,0 @@ -# v2 部署(refactor/v2 分支):与现网 deploy 项目完全隔离(独立库/独立卷/独立网络), -# 对外复用 official.inkreach.cc 域名,由现网 nginx 按路径分流: -# https://official.inkreach.cc/v2/admin/ -> 本栈 admin(SPA) -# https://official.inkreach.cc/v2-api/ -> 本栈 api(去掉前缀后转发) -# 本栈两容器挂到外部网络 inkreach-shared,与 deploy-admin-1 互通(别名 v2-api / v2-admin)。 -name: deploy-v2 - -services: - postgres: - image: postgres:16-alpine - restart: unless-stopped - environment: - POSTGRES_USER: inkreach - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_DB: inkreach - volumes: - - pgdata:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U inkreach -d inkreach"] - interval: 10s - timeout: 5s - retries: 10 - networks: - - default - - api: - build: - context: .. - dockerfile: deploy/api.Dockerfile - restart: unless-stopped - depends_on: - postgres: - condition: service_healthy - environment: - NODE_ENV: production - PORT: 3001 - DATABASE_URL: postgresql://inkreach:${POSTGRES_PASSWORD}@postgres:5432/inkreach - JWT_SECRET: ${JWT_SECRET} - CORS_ORIGINS: "*" - # 激活 product-family 聚合公开读路径(现网 v1 未设置,保持旧行为,便于对比) - PUBLIC_DETAIL_FROM_FAMILY: "true" - volumes: - - uploads:/app/uploads - networks: - default: - shared: - aliases: - - v2-api - - admin: - build: - context: .. - dockerfile: deploy/admin.Dockerfile - args: - VITE_API_BASE: /v2-api/ - restart: unless-stopped - depends_on: - - api - volumes: - - ./nginx/admin.v2.conf:/etc/nginx/conf.d/default.conf:ro - networks: - default: - shared: - aliases: - - v2-admin - -networks: - default: - shared: - external: true - name: inkreach-shared - -volumes: - pgdata: - uploads: \ No newline at end of file diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index a719afe..9b04a89 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,5 +1,12 @@ +# 单栈部署(2026-09-03 主干收敛后,一切以 v2 为准): +# https://official.inkreach.cc/v2/admin/ -> v2-admin(SPA) +# https://official.inkreach.cc/v2-api/ -> v2-api(小程序/后台同路径,去前缀转发) +# https://official.inkreach.cc/public/ -> v2-api(H5 历史构建同源 API) +# /uploads/ /assets/ -> v2-api;证书续期走 certbot 挂载;边缘入口为 admin 服务。 +# v1(旧栈 api+postgres)已退役:容器停用未删,最终档案在 deploy/backups/consolidation-*/。 +# v2 数据卷沿用原 deploy-v2 项目卷(external 引用),数据未迁移未改动。 services: - postgres: + v2-postgres: image: postgres:16-alpine restart: unless-stopped environment: @@ -7,40 +14,54 @@ services: POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: inkreach volumes: - - pgdata:/var/lib/postgresql/data + - v2-pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U inkreach -d inkreach"] interval: 10s timeout: 5s retries: 10 - # No ports exposed: only reachable from the compose network - api: + v2-api: build: context: .. dockerfile: deploy/api.Dockerfile restart: unless-stopped depends_on: - postgres: + v2-postgres: condition: service_healthy environment: NODE_ENV: production PORT: 3001 - DATABASE_URL: postgresql://inkreach:${POSTGRES_PASSWORD}@postgres:5432/inkreach + DATABASE_URL: postgresql://inkreach:${POSTGRES_PASSWORD}@v2-postgres:5432/inkreach JWT_SECRET: ${JWT_SECRET} CORS_ORIGINS: "*" + # 激活 product-family 聚合公开读路径 + PUBLIC_DETAIL_FROM_FAMILY: "true" volumes: - - uploads:/app/uploads + - v2-uploads:/app/uploads + v2-admin: + build: + context: .. + dockerfile: deploy/admin.Dockerfile + args: + VITE_API_BASE: /v2-api/ + restart: unless-stopped + depends_on: + - v2-api + volumes: + - ./nginx/admin.v2.conf:/etc/nginx/conf.d/default.conf:ro + + # 边缘入口:80/443、证书、全站路由与静态资源(/、/admin/、/h5/ 为历史构建,保留展示) admin: build: context: .. dockerfile: deploy/admin.Dockerfile args: - VITE_API_BASE: /api + VITE_API_BASE: /v2-api/ restart: unless-stopped depends_on: - - api + - v2-api ports: - "80:80" - "443:443" @@ -48,20 +69,11 @@ services: - ./nginx/admin.conf:/etc/nginx/conf.d/default.conf:ro - ./certbot/www:/var/www/certbot:ro - ./certbot/acme:/etc/nginx/certs:ro - extra_hosts: - - "host.docker.internal:host-gateway" - networks: - default: - shared: - # 接入 v2 栈的共享网络,使 /v2/* 的 proxy_pass 能解析 v2-admin / v2-api - aliases: - - v1-admin volumes: - pgdata: - uploads: - -networks: - shared: + v2-pgdata: external: true - name: inkreach-shared + name: deploy-v2_pgdata + v2-uploads: + external: true + name: deploy-v2_uploads diff --git a/deploy/nginx/admin.conf b/deploy/nginx/admin.conf index c2d1c19..a77f5ac 100644 --- a/deploy/nginx/admin.conf +++ b/deploy/nginx/admin.conf @@ -88,25 +88,18 @@ server { # Uploaded files served by the API location /uploads/ { - proxy_pass http://api:3001/uploads/; + proxy_pass http://v2-api:3001/uploads/; proxy_set_header Host $host; } # Static product assets served by the API location /assets/ { - proxy_pass http://api:3001/assets/; - proxy_set_header Host $host; - } - - # Product-center icons maintained in the v2 repo — serve from the v2 api - # (more specific prefix than /assets/, so it takes precedence) - location /assets/product-center/ { - proxy_pass http://v2-api:3001/assets/product-center/; + proxy_pass http://v2-api:3001/assets/; proxy_set_header Host $host; } # Website placeholder until the public site is deployed location / { - return 302 /admin/; + return 302 /v2/admin/; } } diff --git a/docs/references/structs.md b/docs/references/structs.md index 34aa5bc..0aecb10 100644 --- a/docs/references/structs.md +++ b/docs/references/structs.md @@ -40,6 +40,18 @@ inkreach-official/ 启动顺序:先启动 `apps/api`,再启动另两个。 +## 生产部署(单栈,2026-09-03 收敛后) + +- 唯一部署源:本仓库 develop(`/opt/inkreach`),`deploy/docker-compose.yml` 单 compose + 编排 4 容器:`admin`(边缘 nginx,80/443 + 证书 + 全站路由)、`v2-api`、`v2-admin`、 + `v2-postgres`(数据卷 `deploy-v2_pgdata` external 引用,v2 数据未迁移)。 +- 域名路由:`/v2/admin/`(SPA)、`/v2-api/`(小程序/后台 API,去前缀转发)、`/public/` + (H5 同源 API)、`/uploads/`、`/assets/` 均由 v2-api 服务;`/` 302 到 `/v2/admin/`。 +- v1(旧 api+postgres,曾支撑 `/public/` 与旧后台)已退役:切换时容器停用未删, + 库终档与全部配置快照及回滚手册见 `deploy/backups/consolidation-*/RESTORE.md`。 +- 原 v2 独立栈(`docker-compose.v2.yml`、`/opt/inkreach-v2` 检出)已并入单栈并删除, + 其血统(refactor/v2)已完全合入 develop;后续所有开发只走 develop。 + ## 子项目 1:apps/api(后端,@inkreach/api) ```