services: skill-scanner: image: ${SKILLHUB_SCANNER_IMAGE:-ghcr.io/iflytek/skillhub-scanner}:${SKILLHUB_VERSION:-latest} restart: unless-stopped environment: SKILL_SCANNER_LLM_API_KEY: ${SKILL_SCANNER_LLM_API_KEY:-} SKILL_SCANNER_LLM_BASE_URL: ${SKILL_SCANNER_LLM_BASE_URL:-} SKILL_SCANNER_LLM_MODEL: ${SKILL_SCANNER_LLM_MODEL:-} healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8000/health"] interval: 10s timeout: 5s retries: 10 postgres: image: ${POSTGRES_IMAGE:-postgres:16-alpine} restart: unless-stopped ports: - "${POSTGRES_BIND_ADDRESS:-127.0.0.1}:${POSTGRES_PORT:-5432}:5432" environment: POSTGRES_DB: ${POSTGRES_DB:-skillhub} POSTGRES_USER: ${POSTGRES_USER:-skillhub} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-skillhub_demo} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-skillhub} -d ${POSTGRES_DB:-skillhub}"] interval: 5s timeout: 5s retries: 10 redis: image: ${REDIS_IMAGE:-redis:7-alpine} restart: unless-stopped ports: - "${REDIS_BIND_ADDRESS:-127.0.0.1}:${REDIS_PORT:-6379}:6379" command: ["redis-server", "--appendonly", "yes"] volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 5s retries: 10 server: image: ${SKILLHUB_SERVER_IMAGE:-ghcr.io/iflytek/skillhub-server}:${SKILLHUB_VERSION:-latest} restart: unless-stopped ports: - "${API_PORT:-8080}:8080" environment: SPRING_PROFILES_ACTIVE: docker SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB:-skillhub} SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER:-skillhub} SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:-skillhub_demo} REDIS_HOST: redis REDIS_PORT: 6379 SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-false} SKILLHUB_PUBLIC_BASE_URL: ${SKILLHUB_PUBLIC_BASE_URL:-} DEVICE_AUTH_VERIFICATION_URI: ${DEVICE_AUTH_VERIFICATION_URI:-} SKILLHUB_STORAGE_PROVIDER: ${SKILLHUB_STORAGE_PROVIDER:-s3} STORAGE_BASE_PATH: /var/lib/skillhub/storage SKILLHUB_STORAGE_S3_ENDPOINT: ${SKILLHUB_STORAGE_S3_ENDPOINT:-} SKILLHUB_STORAGE_S3_PUBLIC_ENDPOINT: ${SKILLHUB_STORAGE_S3_PUBLIC_ENDPOINT:-} SKILLHUB_STORAGE_S3_BUCKET: ${SKILLHUB_STORAGE_S3_BUCKET:-skillhub} SKILLHUB_STORAGE_S3_ACCESS_KEY: ${SKILLHUB_STORAGE_S3_ACCESS_KEY:-} SKILLHUB_STORAGE_S3_SECRET_KEY: ${SKILLHUB_STORAGE_S3_SECRET_KEY:-} SKILLHUB_STORAGE_S3_REGION: ${SKILLHUB_STORAGE_S3_REGION:-us-east-1} SKILLHUB_STORAGE_S3_FORCE_PATH_STYLE: ${SKILLHUB_STORAGE_S3_FORCE_PATH_STYLE:-false} SKILLHUB_STORAGE_S3_AUTO_CREATE_BUCKET: ${SKILLHUB_STORAGE_S3_AUTO_CREATE_BUCKET:-false} SKILLHUB_STORAGE_S3_PRESIGN_EXPIRY: ${SKILLHUB_STORAGE_S3_PRESIGN_EXPIRY:-PT10M} SKILLHUB_SECURITY_SCANNER_ENABLED: ${SKILLHUB_SECURITY_SCANNER_ENABLED:-true} SKILLHUB_SECURITY_SCANNER_URL: http://skill-scanner:8000 SKILLHUB_SECURITY_SCANNER_MODE: upload BOOTSTRAP_ADMIN_ENABLED: ${BOOTSTRAP_ADMIN_ENABLED:-false} BOOTSTRAP_ADMIN_USER_ID: ${BOOTSTRAP_ADMIN_USER_ID:-docker-admin} BOOTSTRAP_ADMIN_USERNAME: ${BOOTSTRAP_ADMIN_USERNAME:-admin} BOOTSTRAP_ADMIN_PASSWORD: ${BOOTSTRAP_ADMIN_PASSWORD:-ChangeMe!2026} BOOTSTRAP_ADMIN_DISPLAY_NAME: ${BOOTSTRAP_ADMIN_DISPLAY_NAME:-Admin} BOOTSTRAP_ADMIN_EMAIL: ${BOOTSTRAP_ADMIN_EMAIL:-admin@skillhub.local} OAUTH2_GITHUB_CLIENT_ID: ${OAUTH2_GITHUB_CLIENT_ID:-local-placeholder} OAUTH2_GITHUB_CLIENT_SECRET: ${OAUTH2_GITHUB_CLIENT_SECRET:-local-placeholder} SPRING_MAIL_HOST: ${SPRING_MAIL_HOST:-} SPRING_MAIL_PORT: ${SPRING_MAIL_PORT:-25} SPRING_MAIL_USERNAME: ${SPRING_MAIL_USERNAME:-} SPRING_MAIL_PASSWORD: ${SPRING_MAIL_PASSWORD:-} SPRING_MAIL_SMTP_AUTH: ${SPRING_MAIL_SMTP_AUTH:-false} SPRING_MAIL_SMTP_STARTTLS_ENABLE: ${SPRING_MAIL_SMTP_STARTTLS_ENABLE:-false} SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE: ${SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_ENABLE:-false} SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST: ${SPRING_MAIL_PROPERTIES_MAIL_SMTP_SSL_TRUST:-} SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY: ${SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY:-PT10M} SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS: ${SKILLHUB_AUTH_PASSWORD_RESET_FROM_ADDRESS:-noreply@skillhub.local} SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME: ${SKILLHUB_AUTH_PASSWORD_RESET_FROM_NAME:-SkillHub} volumes: - skillhub_storage:/var/lib/skillhub/storage depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:8080/actuator/health"] interval: 10s timeout: 5s retries: 12 start_period: 60s web: image: ${SKILLHUB_WEB_IMAGE:-ghcr.io/iflytek/skillhub-web}:${SKILLHUB_VERSION:-latest} restart: unless-stopped ports: - "${WEB_PORT:-80}:80" environment: SKILLHUB_API_UPSTREAM: ${SKILLHUB_API_UPSTREAM:-http://server:8080} SKILLHUB_WEB_API_BASE_URL: ${SKILLHUB_WEB_API_BASE_URL:-} SKILLHUB_PUBLIC_BASE_URL: ${SKILLHUB_PUBLIC_BASE_URL:-} depends_on: server: condition: service_healthy healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1/nginx-health"] interval: 10s timeout: 5s retries: 12 start_period: 10s volumes: postgres_data: redis_data: skillhub_storage: