sub2api/deploy/docker-compose.yml
win 888b7eeb21
Some checks failed
CI / test (push) Failing after 3s
CI / golangci-lint (push) Failing after 3s
Security Scan / backend-security (push) Failing after 2s
Security Scan / frontend-security (push) Failing after 2m0s
feat: add opus-4-7 support + nginx load balancer docker-compose
2026-04-17 11:43:38 +08:00

231 lines
8.0 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.

# =============================================================================
# Sub2API Docker Compose Configuration (负载均衡版)
# =============================================================================
# Quick Start:
# 1. Copy .env.example to .env and configure
# 2. docker compose up -d
# 3. Check logs: docker compose logs -f
# 4. Access: http://localhost (via nginx)
#
# 扩缩容:
# docker compose up -d --scale sub2api=5 # 扩到 5 个实例
# docker compose up -d --scale sub2api=2 # 缩回 2 个实例
#
# 注意事项:
# - JWT_SECRET / TOTP_ENCRYPTION_KEY 必须固定,多实例共享同一个值
# - PostgreSQL / Redis 单实例,不参与水平扩展
# - postgres 端口默认不对外暴露,如需调试取消注释 127.0.0.1:5433:5432
# - redis 端口默认不对外暴露,如需调试取消注释 127.0.0.1:6380:6379
# =============================================================================
services:
# ===========================================================================
# Nginx 负载均衡(入口)
# ===========================================================================
nginx:
image: nginx:alpine
container_name: sub2api-nginx
restart: unless-stopped
ulimits:
nofile:
soft: 65535
hard: 65535
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/certs:/etc/nginx/certs:ro
depends_on:
sub2api:
condition: service_healthy
networks:
- sub2api-network
healthcheck:
test: [ "CMD", "wget", "-q", "-T", "3", "-O", "/dev/null", "http://localhost/health" ]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# ===========================================================================
# Sub2API Application多实例通过 --scale 控制数量)
# ===========================================================================
sub2api:
image: docker.io/zfc931912343/sub2api:latest
restart: unless-stopped
ulimits:
nofile:
soft: 100000
hard: 100000
# 不直接暴露端口,由 nginx 代理
expose:
- "8080"
volumes:
- sub2api_data:/app/data
# Optional: 挂载自定义 config.yaml先从 config.example.yaml 复制并修改)
# - ./config.yaml:/app/data/config.yaml
# Optional: 自定义 Codex instructions 模板
# - ./codex-instructions.md.tmpl:/app/data/codex-instructions.md.tmpl:ro
environment:
- AUTO_SETUP=true
# --- Server ---
- SERVER_HOST=0.0.0.0
- SERVER_PORT=8080
- SERVER_MODE=${SERVER_MODE:-release}
- RUN_MODE=${RUN_MODE:-standard}
# --- Database (PostgreSQL) ---
- DATABASE_HOST=postgres
- DATABASE_PORT=5432
- DATABASE_USER=${POSTGRES_USER:-sub2api}
- DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
- DATABASE_DBNAME=${POSTGRES_DB:-sub2api}
- DATABASE_SSLMODE=disable
- DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50}
- DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10}
- DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30}
- DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5}
# --- Redis ---
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
- REDIS_DB=${REDIS_DB:-0}
- REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024}
- REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10}
- REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false}
# --- Admin仅首次启动生效---
- ADMIN_EMAIL=${ADMIN_EMAIL:-admin@sub2api.local}
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
# --- JWT多实例必须固定否则重启后 session 失效)---
# 生成: openssl rand -hex 32
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required for multi-instance}
- JWT_EXPIRE_HOUR=${JWT_EXPIRE_HOUR:-24}
# --- TOTP 2FA多实例必须固定否则 2FA 失效)---
# 生成: openssl rand -hex 32
- TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY:?TOTP_ENCRYPTION_KEY is required for multi-instance}
# --- Timezone ---
- TZ=${TZ:-Asia/Shanghai}
# --- Gemini OAuth ---
- GEMINI_OAUTH_CLIENT_ID=${GEMINI_OAUTH_CLIENT_ID:-}
- GEMINI_OAUTH_CLIENT_SECRET=${GEMINI_OAUTH_CLIENT_SECRET:-}
- GEMINI_OAUTH_SCOPES=${GEMINI_OAUTH_SCOPES:-}
- GEMINI_QUOTA_POLICY=${GEMINI_QUOTA_POLICY:-}
- GEMINI_CLI_OAUTH_CLIENT_SECRET=${GEMINI_CLI_OAUTH_CLIENT_SECRET:-}
- ANTIGRAVITY_OAUTH_CLIENT_SECRET=${ANTIGRAVITY_OAUTH_CLIENT_SECRET:-}
# --- Security ---
- SECURITY_URL_ALLOWLIST_ENABLED=${SECURITY_URL_ALLOWLIST_ENABLED:-false}
- SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=${SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP:-false}
- SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=${SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS:-false}
- SECURITY_URL_ALLOWLIST_UPSTREAM_HOSTS=${SECURITY_URL_ALLOWLIST_UPSTREAM_HOSTS:-}
# --- Update Proxy国内机器可配置代理访问 GitHub---
- UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
networks:
- sub2api-network
healthcheck:
test: [ "CMD", "wget", "-q", "-T", "5", "-O", "/dev/null", "http://localhost:8080/health" ]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# ===========================================================================
# PostgreSQL Database
# ===========================================================================
postgres:
image: postgres:18-alpine
container_name: sub2api-postgres
restart: unless-stopped
ulimits:
nofile:
soft: 100000
hard: 100000
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
# postgres:18-alpine 默认 PGDATA 在镜像内部匿名卷,必须显式指定才能持久化到命名卷
- PGDATA=/var/lib/postgresql/data
- POSTGRES_USER=${POSTGRES_USER:-sub2api}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
- POSTGRES_DB=${POSTGRES_DB:-sub2api}
- TZ=${TZ:-Asia/Shanghai}
networks:
- sub2api-network
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sub2api} -d ${POSTGRES_DB:-sub2api}" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
# 默认不对外暴露,如需本地调试取消注释
# ports:
# - "127.0.0.1:5433:5432"
# ===========================================================================
# Redis Cache
# ===========================================================================
redis:
image: redis:8-alpine
container_name: sub2api-redis
restart: unless-stopped
ulimits:
nofile:
soft: 100000
hard: 100000
volumes:
- redis_data:/data
command: >
sh -c '
redis-server
--save 60 1
--appendonly yes
--appendfsync everysec
${REDIS_PASSWORD:+--requirepass "$REDIS_PASSWORD"}'
environment:
- TZ=${TZ:-Asia/Shanghai}
- REDISCLI_AUTH=${REDIS_PASSWORD:-}
networks:
- sub2api-network
healthcheck:
test: [ "CMD", "redis-cli", "ping" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
# 默认不对外暴露,如需本地调试取消注释
# ports:
# - "127.0.0.1:6380:6379"
# =============================================================================
# Volumes
# =============================================================================
volumes:
sub2api_data:
driver: local
postgres_data:
driver: local
redis_data:
driver: local
# =============================================================================
# Networks
# =============================================================================
networks:
sub2api-network:
driver: bridge