Files
BYW-VoiceHub/docker-compose.yml
T
Henry_Du 47d63a48b0
构建 & 部署 BYW VoiceHub / Preflight 语法 & 构建检查 (push) Canceled after 0s
构建 & 部署 BYW VoiceHub / 构建并推送镜像 (push) Canceled after 0s
构建 & 部署 BYW VoiceHub / 部署到生产服务器 (push) Canceled after 0s
fix: 修复 Docker Compose v2 严格类型下 cpus 双引号导致 ParseFloat 报错
2026-09-06 09:41:34 +08:00

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