x-logging: &default-logging driver: json-file options: max-size: ${LOG_MAX_SIZE:-20m} max-file: "${LOG_MAX_FILE:-5}" services: sub2api: image: ${SUB2API_IMAGE:-weishaw/sub2api:latest} container_name: sub2api restart: unless-stopped logging: *default-logging ulimits: nofile: soft: 100000 hard: 100000 ports: - "${BIND_HOST:-127.0.0.1}:${SERVER_PORT:-8080}:8080" volumes: - ./data:/app/data environment: - AUTO_SETUP=true - SERVER_HOST=0.0.0.0 - SERVER_PORT=8080 - SERVER_MODE=${SERVER_MODE:-release} - RUN_MODE=${RUN_MODE:-standard} - TZ=${TZ:-Asia/Shanghai} - 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:-20} - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-5} - DATABASE_CONN_MAX_LIFETIME_MINUTES=30 - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=5 - REDIS_HOST=redis - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=${REDIS_DB:-0} - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-128} - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-4} - REDIS_ENABLE_TLS=false - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@example.com} - ADMIN_PASSWORD=${ADMIN_PASSWORD:?ADMIN_PASSWORD is required} - JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required} - JWT_EXPIRE_HOUR=24 - TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY:?TOTP_ENCRYPTION_KEY is required} - UPDATE_PROXY_URL=${UPDATE_PROXY_URL:-} - 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} depends_on: postgres: condition: service_healthy redis: condition: service_healthy mihomo: condition: service_started 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 postgres: image: ${POSTGRES_IMAGE:-postgres:18-alpine} container_name: sub2api-postgres restart: unless-stopped logging: *default-logging shm_size: 64m volumes: - ./postgres_data:/var/lib/postgresql/data environment: - POSTGRES_USER=${POSTGRES_USER:-sub2api} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - POSTGRES_DB=${POSTGRES_DB:-sub2api} - PGDATA=/var/lib/postgresql/data - TZ=${TZ:-Asia/Shanghai} command: - postgres - -c - max_connections=30 - -c - shared_buffers=64MB - -c - effective_cache_size=256MB - -c - work_mem=2MB - -c - maintenance_work_mem=32MB 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 redis: image: ${REDIS_IMAGE:-redis:8-alpine} container_name: sub2api-redis restart: unless-stopped logging: *default-logging volumes: - ./redis_data:/data command: > sh -c 'redis-server --save 60 1 --appendonly yes --appendfsync everysec $${REDIS_PASSWORD:+--requirepass "$$REDIS_PASSWORD"} $${REDIS_MAXMEMORY:+--maxmemory "$$REDIS_MAXMEMORY" --maxmemory-policy allkeys-lru}' environment: - TZ=${TZ:-Asia/Shanghai} - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_MAXMEMORY=${REDIS_MAXMEMORY:-128mb} - REDISCLI_AUTH=${REDIS_PASSWORD:-} networks: - sub2api-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 5s mihomo: image: ${MIHOMO_IMAGE:-metacubex/mihomo:latest} container_name: sub2api-mihomo restart: unless-stopped logging: *default-logging volumes: - ./mihomo:/root/.config/mihomo environment: - TZ=${TZ:-Asia/Shanghai} networks: - sub2api-network networks: sub2api-network: name: sub2api-network driver: bridge