Files
backend_v2/docker-compose.yml
toom1996 acc0928401 update
2026-10-20 23:11:57 +08:00

141 lines
4.6 KiB
YAML
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.

# 生产部署:蓝绿双槽 + 常驻代理,支持零停机发布
#
# 服务器目录(必须同级):
# /opt/fashion/backend ← 本文件所在(后端仓,部署入口)
# /opt/fashion/test ← 前端仓(默认按 ../test 取,可用 .env 的 WEB_DIR 覆盖)
#
# 浏览器 ──▶ proxy(nginx:80,常驻不重建)
# ├─ /api ──▶ backend_a 或 backend_b
# ├─ / ──▶ web_a 或 web_b
# ├─ 18090(容器内) SSR 取数 → 当前活跃后端
# ├─ 127.0.0.1:18091 前端构建期取 SSG
# └─ 127.0.0.1:18092 管理后台(SSH 隧道)
#
# 首次部署:cp .env.example .env → 填密钥 → ./init-db.sh <sql> → ./deploy.sh all
# 日常发布:./deploy.sh(只更新后端) / ./deploy.sh all / ./deploy.sh --rollback
#
# a/b 两个槽共用同一份镜像标签(RELEASE=时间戳-提交号,不可变),
# deploy.sh 只重建空闲槽,换完 nginx -s reload 即切换。
x-backend-base: &backend-base
image: fashion-backend:${RELEASE:-latest}
restart: unless-stopped
environment:
SERVER_PORT: 8090
SSG_PORT: 8091
BACKSTAGE_PORT: 8092
GIN_MODE: release
HASHID_SECRET: ${HASHID_SECRET:-}
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET 未设置}
SSG_TOKEN: ${SSG_TOKEN:-}
CORS_ALLOW_ORIGINS: ${CORS_ALLOW_ORIGINS:-https://xisoa.com,https://www.xisoa.com}
RATE_LIMIT_ENABLED: ${RATE_LIMIT_ENABLED:-true}
RATE_LIMIT_RPS: ${RATE_LIMIT_RPS:-20}
RATE_LIMIT_BURST: ${RATE_LIMIT_BURST:-40}
# 复用 1Panel 现有 Postgres(宿主 5432)。host-gateway 让容器经宿主访问它。
DB_HOST: host.docker.internal
DB_PORT: 5432
DB_USER: ${DB_USER:-fashion}
DB_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD 未设置}
DB_NAME: ${DB_NAME:-fashion}
INGEST_SECRET: ${INGEST_SECRET:?INGEST_SECRET 未设置}
INGEST_TTL: ${INGEST_TTL:-300}
INGEST_DOWNLOAD_PROXY: ${INGEST_DOWNLOAD_PROXY:-}
INGEST_IMAGE_CONCURRENCY: ${INGEST_IMAGE_CONCURRENCY:-4}
S4_ENABLED: ${S4_ENABLED:-true}
S4_AK: ${S4_AK:?S4_AK 未设置}
S4_SK: ${S4_SK:?S4_SK 未设置}
S4_BUCKET: ${S4_BUCKET:-toomstudio}
S4_ENDPOINT: ${S4_ENDPOINT:-https://s3.bitiful.net}
S4_REGION: ${S4_REGION:-cn-east-1}
S4_BASE_URL: ${S4_BASE_URL:-}
VISION_ENABLED: ${VISION_ENABLED:-false}
VISION_ENDPOINT: ${VISION_ENDPOINT:-http://127.0.0.1:8900}
UPLOAD_DIR: /app/uploads
volumes:
- uploads:/app/uploads
extra_hosts:
- "host.docker.internal:host-gateway"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8090/api/health"]
interval: 10s
timeout: 5s
retries: 6
start_period: 15s
x-web-base: &web-base
image: fashion-web:${RELEASE:-latest}
restart: unless-stopped
environment:
# 容器内的 localhost 是它自己,SSR 取数统一走代理(永远指向活跃后端槽)
BASE_API_SSR: http://proxy:18090
healthcheck:
test: ["CMD", "nc", "-z", "127.0.0.1", "3000"]
interval: 10s
timeout: 3s
retries: 5
start_period: 15s
services:
# ---- 数据库:复用 1Panel 现有 Postgres(连接信息见 .env 的 DB_HOST/DB_PORT/DB_USER/DB_PASSWORD)----
# ---- 常驻代理:整个发布过程中不重建,切换只靠 reload ----
proxy:
image: nginx:1.27-alpine
restart: unless-stopped
ports:
# 只绑宿主回环:80/443 由 1Panel OpenResty 占用,外层反代到 127.0.0.1:${HTTP_PORT}
- "127.0.0.1:${HTTP_PORT:-8080}:80"
- "127.0.0.1:18091:18091" # 前端构建期取 SSG
- "127.0.0.1:18092:18092" # 管理后台(SSH 隧道)
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
# 切换点放在 .deploy/(已被 gitignore),发布时改写它不会弄脏工作区
- ./.deploy/nginx:/etc/nginx/active:ro
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1/healthz"]
interval: 15s
timeout: 3s
retries: 5
start_period: 5s
depends_on:
backend_a:
condition: service_healthy
web_a:
condition: service_started
# ---- 后端双槽 ----
backend_a:
<<: *backend-base
build:
context: .
args:
GOPROXY: ${GOPROXY:-https://goproxy.cn,direct}
backend_b:
<<: *backend-base
# ---- 前端双槽(只跑 Astro node,nginx 在 proxy 里)----
web_a:
<<: *web-base
build:
context: ${WEB_DIR:-../test}
args:
# 走宿主回环的代理 18091,由代理转发到活跃后端槽
BASE_API_SSG: http://127.0.0.1:18091
SSG_TOKEN: ${SSG_TOKEN:-}
network: host
web_b:
<<: *web-base
volumes:
uploads: