162 lines
5.7 KiB
YAML
162 lines
5.7 KiB
YAML
name: BYW VoiceHub (1.7.0.0)
|
|
services:
|
|
# ========================================================================
|
|
# 应用本体 - Nuxt 4 (Node SSR)
|
|
# - 使用两阶段构建 Dockerfile,构建阶段内存友好
|
|
# - PREBUILT=true:告诉 scripts/deploy.js 跳过 npm install 和 nuxt build
|
|
# (因为第一阶段已经 build 好了,产物在 .output/ 里)
|
|
# ========================================================================
|
|
voicehub:
|
|
image: byw-voicehub:1.7.0.0
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
args:
|
|
BUILDKIT_INLINE_CACHE: "1"
|
|
container_name: voicehub-app
|
|
restart: unless-stopped
|
|
ports:
|
|
# 左边是宿主机端口(对外),右边是容器内端口(固定 3000)
|
|
# 如果要套 Nginx,就只监听 127.0.0.1:4456:3000 不直接暴露外网
|
|
- "4456:3000"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
redis:
|
|
condition: service_healthy
|
|
env_file:
|
|
# 把密码、密钥都写在项目根的 .env 里,不要直接写进这个 yaml
|
|
- .env
|
|
environment:
|
|
# ===== 运行时基础(可以被 .env 覆盖) =====
|
|
NODE_ENV: production
|
|
PORT: 3000
|
|
HOST: 0.0.0.0
|
|
PREBUILT: "true"
|
|
SKIP_INSTALL: "true"
|
|
SKIP_BUILD: "true"
|
|
NITRO_PRESET: node-server
|
|
|
|
# ===== 数据库连接串(.env 写了就用 .env,没写就自动拼 compose 内部 postgres 服务) =====
|
|
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-voicehub}:${POSTGRES_PASSWORD:-voicehub}@postgres:5432/${POSTGRES_DB:-voicehub}?sslmode=disable}
|
|
|
|
# ===== Redis 连接串(同上,自动拼内部 redis 服务) =====
|
|
REDIS_URL: ${REDIS_URL:-redis://${REDIS_PASSWORD:+:${REDIS_PASSWORD}@}redis:6379/0}
|
|
|
|
# ===== 会话/Token(必须在 .env 里设,这里给一个占位提醒) =====
|
|
JWT_SECRET: ${JWT_SECRET:-请在.env里设置JWT_SECRET用openssl rand -hex 32生成}
|
|
|
|
# ===== 应用默认(可在 .env 覆盖,不会覆盖 .env 里同名字段) =====
|
|
NUXT_PUBLIC_SITE_URL: ${NUXT_PUBLIC_SITE_URL:-http://127.0.0.1:4456}
|
|
NUXT_PUBLIC_SITE_TITLE: ${NUXT_PUBLIC_SITE_TITLE:-校园广播站点歌系统}
|
|
NUXT_PUBLIC_DEFAULT_THEME: ${NUXT_PUBLIC_DEFAULT_THEME:-dark}
|
|
NUXT_PUBLIC_ENABLED_THEMES: ${NUXT_PUBLIC_ENABLED_THEMES:-dark,light}
|
|
|
|
# ===== 日志/性能 =====
|
|
NODE_OPTIONS: ${NODE_OPTIONS:-"--max-old-space-size=768"}
|
|
# 2C4G 机器的推荐配置(.env 可覆盖);小机器 1C2G 也能跑
|
|
# ⚠️ 注意:cpus 默认值不能加双引号!新版 Docker Compose v2 严格类型:
|
|
# 加引号会解析为字符串 '"1.5"' → ParseFloat 失败报错
|
|
mem_limit: ${APP_MEM_LIMIT:-1400m}
|
|
mem_reservation: ${APP_MEM_RESERVATION:-384m}
|
|
cpus: ${APP_CPUS:-1.5}
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: ${APP_CPUS_LIMIT:-2}
|
|
memory: ${APP_MEM_LIMIT:-1400M}
|
|
reservations:
|
|
cpus: ${APP_CPUS_RESERVATION:-0.5}
|
|
memory: ${APP_MEM_RESERVATION:-384M}
|
|
healthcheck:
|
|
# 30s 后开始检查,每 15s 一次,连续 3 次失败就重启
|
|
test:
|
|
[
|
|
"CMD",
|
|
"node",
|
|
"-e",
|
|
"fetch('http://127.0.0.1:3000/').then(r=>{process.exit(r.ok?0:1)}).catch(()=>process.exit(1))"
|
|
]
|
|
interval: 15s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
networks:
|
|
- voicehub-net
|
|
volumes:
|
|
# (可选)把自定义 logo/上传资源挂到宿主机
|
|
- voicehub-uploads:/app/app/public/uploads:rw
|
|
|
|
# ========================================================================
|
|
# PostgreSQL 16 - 主数据库
|
|
# ========================================================================
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: voicehub-postgres
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-voicehub}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-请在.env里改这个密码}
|
|
POSTGRES_DB: ${POSTGRES_DB:-voicehub}
|
|
PGDATA: /var/lib/postgresql/data/pgdata
|
|
# .env 里没设 DATABASE_URL 时,自动拼一份给 app 用
|
|
# (如果 .env 里已经写了外部 Postgres,就以 .env 为准)
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-voicehub} -d ${POSTGRES_DB:-voicehub}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 10
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
# 如需从宿主机用 Navicat 连,取消下一行注释
|
|
# ports:
|
|
# - "127.0.0.1:5433:5432"
|
|
mem_limit: ${PG_MEM_LIMIT:-1200m}
|
|
mem_reservation: ${PG_MEM_RESERVATION:-256m}
|
|
cpus: ${PG_CPUS:-"1.0"}
|
|
networks:
|
|
- voicehub-net
|
|
|
|
# ========================================================================
|
|
# Redis 7 - 缓存 / 会话 / 限流 / 队列
|
|
# ========================================================================
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: voicehub-redis
|
|
restart: unless-stopped
|
|
command: >
|
|
sh -c "
|
|
if [ -n \"$$REDIS_PASSWORD\" ]; then
|
|
redis-server --appendonly yes --requirepass \"$$REDIS_PASSWORD\"
|
|
else
|
|
redis-server --appendonly yes
|
|
fi
|
|
"
|
|
environment:
|
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
volumes:
|
|
- redis-data:/data
|
|
mem_limit: ${REDIS_MEM_LIMIT:-384m}
|
|
mem_reservation: ${REDIS_MEM_RESERVATION:-64m}
|
|
cpus: ${REDIS_CPUS:-0.5}
|
|
networks:
|
|
- voicehub-net
|
|
|
|
volumes:
|
|
postgres-data:
|
|
name: voicehub-postgres-data
|
|
redis-data:
|
|
name: voicehub-redis-data
|
|
voicehub-uploads:
|
|
name: voicehub-uploads
|
|
|
|
networks:
|
|
voicehub-net:
|
|
name: voicehub-net
|
|
driver: bridge
|