topfans/docker/docker-compose.prod.yml
2026-06-17 11:59:51 +08:00

634 lines
17 KiB
YAML
Raw Permalink 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.

# ===================================================================
# TopFans Docker Compose - Production (4G RAM, 2 CPU)
# ===================================================================
# Usage:
# docker-compose -f docker-compose.prod.yml --profile prod up -d
# ===================================================================
# 显式声明 project 名称,与 TopFans-activity-admin 仓库的 docker-compose.admin.yml
# 完全隔离。这样 `docker ps --filter project=topfans-main` / `down --remove-orphans`
# 永远只动本仓库的容器,不会误删 admin 仓的 topfans-adminbackend / topfans-adminfrontend。
# (历史教训:2026-06-12 因 deploy.sh 用 name=topfans- 前缀过滤误删 admin 容器 18 分钟)
name: topfans-main
x-common-env: &common-env
GIN_MODE: release
ENV: production
LOG_LEVEL: info
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
DB_SSLMODE: disable
x-postgres-env: &postgres-env
POSTGRES_DB: topfans
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres123}
POSTGRES_MAX_CONNECTIONS: 100
POSTGRES_SHARED_BUFFERS: 128MB
POSTGRES_WORK_MEM: 8MB
POSTGRES_MAINTENANCE_WORK_MEM: 64MB
POSTGRES_EFFECTIVE_CACHE_SIZE: 512MB
POSTGRES_CHECKPOINT_COMPLETION_TARGET: 0.9
POSTGRES_WAL_BUFFERS: 8MB
x-healthcheck: &healthcheck
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
services:
# ==================== Database ====================
postgres:
image: postgres:latest
container_name: topfans-postgres
restart: always
environment:
<<: *postgres-env
volumes:
- postgres_data:/var/lib/postgresql
ports:
- "5432:5432"
networks:
- topfans-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d topfans"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 400M
reservations:
memory: 128M
# ==================== Redis ====================
redis:
image: redis:latest
container_name: topfans-redis
restart: always
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
ports:
- "6379:6379"
networks:
- topfans-net
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
interval: 30s
timeout: 10s
retries: 5
deploy:
resources:
limits:
memory: 256M
reservations:
memory: 64M
# ==================== Flyway Migration ====================
# flyway:
# image: flyway/flyway:10
# container_name: topfans-flyway
# restart: "no"
# depends_on:
# postgres:
# condition: service_healthy
# environment:
# - FLYWAY_URL=jdbc:postgresql://postgres:5432/topfans
# - FLYWAY_USER=postgres
# - FLYWAY_PASSWORD=${DB_PASSWORD:-postgres123}
# - FLYWAY_SCHEMAS=public
# - FLYWAY_PLACEHOLDER_REPLACEMENT=true
# volumes:
# - ./sql/migrations:/flyway/sql
# - flyway_data:/flyway/data
# command: migrate -baselineOnMigrate=true
# networks:
# - topfans-net
# ==================== Dubbo Services ====================
userservice:
image: topfans/userservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: userservice
container_name: topfans-userservice
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
PORT: 20000
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
REDIS_HOST: topfans-redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
REDIS_DB: 0
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- topfans-net
expose:
- "20000"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21000/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 150M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
assetservice:
image: topfans/assetservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: assetservice
container_name: topfans-assetservice
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
PORT: 20003
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
USER_SERVICE_URL: tri://userservice:20000
depends_on:
userservice:
condition: service_started
networks:
- topfans-net
expose:
- "20003"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21003/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 200M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
socialservice:
image: topfans/socialservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: socialservice
container_name: topfans-socialservice
restart: always
environment:
<<: *common-env
PORT: 20002
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
USER_SERVICE_URL: tri://userservice:20000
ASSET_SERVICE_URL: tri://assetservice:20003
depends_on:
userservice:
condition: service_started
assetservice:
condition: service_started
networks:
- topfans-net
expose:
- "20002"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21002/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 150M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
galleryservice:
image: topfans/galleryservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: galleryservice
container_name: topfans-galleryservice
restart: always
environment:
<<: *common-env
PORT: 20001
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
USER_SERVICE_URL: tri://userservice:20000
ASSET_SERVICE_URL: tri://assetservice:20003
TASK_SERVICE_URL: tri://taskservice:20006
depends_on:
userservice:
condition: service_started
assetservice:
condition: service_started
networks:
- topfans-net
expose:
- "20001"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21001/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 150M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
activityservice:
image: topfans/activityservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: activityservice
container_name: topfans-activityservice
restart: always
environment:
<<: *common-env
PORT: 20004
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
USER_SERVICE_URL: tri://userservice:20000
REDIS_HOST: topfans-redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
REDIS_DB: 0
depends_on:
userservice:
condition: service_started
redis:
condition: service_healthy
networks:
- topfans-net
expose:
- "20004"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21004/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 100M
cpus: '0.5'
reservations:
memory: 32M
cpus: '0.25'
taskservice:
image: topfans/taskservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: taskservice
container_name: topfans-taskservice
restart: always
environment:
<<: *common-env
PORT: 20006
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
USER_SERVICE_URL: tri://userservice:20000
GALLERY_SERVICE_URL: tri://galleryservice:20001
depends_on:
userservice:
condition: service_started
networks:
- topfans-net
expose:
- "20006"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21006/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 150M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
starbookservice:
image: topfans/starbookservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: starbookservice
container_name: topfans-starbookservice
restart: always
environment:
<<: *common-env
PORT: 20005
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
ASSET_SERVICE_URL: tri://assetservice:20003
depends_on:
userservice:
condition: service_started
assetservice:
condition: service_started
networks:
- topfans-net
expose:
- "20005"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21005/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 150M
cpus: '0.5'
reservations:
memory: 64M
cpus: '0.25'
# ==================== AI Chat Service ====================
aichatservice:
image: topfans/aichatservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: aichatservice
container_name: topfans-aichatservice
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
PORT: 20008
DB_HOST: postgres
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: ${DB_PASSWORD:-postgres123}
DB_NAME: topfans
REDIS_HOST: topfans-redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
REDIS_DB: 0
depends_on:
userservice:
condition: service_started
redis:
condition: service_healthy
networks:
- topfans-net
expose:
- "20008"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21008/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 512M
cpus: '1'
reservations:
memory: 256M
cpus: '0.5'
# ==================== Laser Compositor Service (镭射卡 6 层合成) ====================
lasercompositor:
image: topfans/lasercompositor:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: lasercompositor
# 跳过 pull(本地无 push 到 registry),直接走 build
pull_policy: never
container_name: topfans-lasercompositor
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
COMPOSITOR_PORT: 7002
# OSS_* 全部走 env_file: .env.prod
networks:
- topfans-net
expose:
- "7002"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7002/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 300M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
# ==================== Statistic Service (数据看板微服务) ====================
statisticservice:
image: topfans/statisticservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: statisticservice
container_name: topfans-statisticservice
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
PORT: 20009
# statistic 服务使用独立 schema与 common-env 中的 DB_* 解耦)
STATISTIC_DB_HOST: postgres
STATISTIC_DB_PORT: 5432
STATISTIC_DB_USER: postgres
STATISTIC_DB_PASSWORD: ${DB_PASSWORD:-postgres123}
STATISTIC_DB_NAME: topfans
STATISTIC_DB_SSLMODE: disable
STATISTIC_DB_SCHEMA: statistic
# Redis
STATISTIC_REDIS_HOST: topfans-redis
STATISTIC_REDIS_PORT: 6379
STATISTIC_REDIS_PASSWORD: ${REDIS_PASSWORD:-123456}
STATISTIC_REDIS_DB: 0
# 跨服务调用 userService看板 GetTodayOverview 需要 crystal_balance
USER_SERVICE_URL: tri://userservice:20000
depends_on:
userservice:
condition: service_started
redis:
condition: service_healthy
networks:
- topfans-net
expose:
- "20009"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21009/healthz || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 300M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
# 通知服务(手机推送 / 通知中心读写)
# 推送走阿里云 uniCloud sendMessage,生产 URL 在 .env.prod 注入。
# 留空 PUSH_URL 会让 main.go 降级为 NoopPusher(只写库,不真推手机)。
notificationservice:
image: topfans/notificationservice:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: notificationservice
container_name: topfans-notificationservice
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
PORT: 20010
# 默认从 .env.prod 读取;部署时如需覆盖可在 docker-compose 启动时
# 用 NOTIFICATION_PUSH_URL=... 注入(只对当前启动生效,不入 git)。
PUSH_ENABLED: ${NOTIFICATION_PUSH_ENABLED:-true}
PUSH_URL: ${NOTIFICATION_PUSH_URL:-https://env-00jy6bcqqwy6.dev-hz.cloudbasefunction.cn/sendMessage}
PUSH_TIMEOUT_MS: ${NOTIFICATION_PUSH_TIMEOUT_MS:-4000}
depends_on:
postgres:
condition: service_healthy
networks:
- topfans-net
expose:
- "20010"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:21010/healthz || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 300M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
# ==================== API Gateway ====================
gateway:
image: topfans/gateway:latest
build:
context: ..
dockerfile: docker/Dockerfile.services
target: gateway
container_name: topfans-gateway
restart: always
env_file:
- .env.prod
environment:
<<: *common-env
SERVER_PORT: 8080
DUBBO_USER_SERVICE_URL: tri://userservice:20000
DUBBO_SOCIAL_SERVICE_URL: tri://socialservice:20002
DUBBO_ASSET_SERVICE_URL: tri://assetservice:20003
DUBBO_GALLERY_SERVICE_URL: tri://galleryservice:20001
DUBBO_ACTIVITY_SERVICE_URL: tri://activityservice:20004
DUBBO_TASK_SERVICE_URL: tri://taskservice:20006
DUBBO_STARBOOK_SERVICE_URL: tri://starbookservice:20005
DUBBO_AI_CHAT_SERVICE_URL: tri://aichatservice:20008
DUBBO_STATISTIC_SERVICE_URL: tri://statisticservice:20009
DUBBO_NOTIFICATION_SERVICE_URL: tri://notificationservice:20010
LASER_COMPOSITOR_URL: http://lasercompositor:7002
# 抠图人像扣底、OSS、Dify、JWT、Redis 全部走 env_file: .env.prod
REDIS_HOST: topfans-redis
REDIS_PORT: 6379
REDIS_DB: 0
depends_on:
userservice:
condition: service_started
assetservice:
condition: service_started
socialservice:
condition: service_started
galleryservice:
condition: service_started
activityservice:
condition: service_started
taskservice:
condition: service_started
starbookservice:
condition: service_started
aichatservice:
condition: service_started
statisticservice:
condition: service_started
notificationservice:
condition: service_started
lasercompositor:
condition: service_started
redis:
condition: service_healthy
networks:
topfans-net:
aliases:
- newbackend
ports:
- "8080:8080"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1"]
<<: *healthcheck
deploy:
resources:
limits:
memory: 300M
cpus: '0.5'
reservations:
memory: 128M
cpus: '0.25'
volumes:
postgres_data:
flyway_data:
networks:
topfans-net:
driver: bridge
external: true