# ============================================================================= # Sentry Self-Hosted - 崩溃收集与错误追踪 # ============================================================================= # # 功能: # - 崩溃收集(Flutter + Android/iOS 原生层) # - 错误追踪与符号化 # - 性能监控 # - Session Replay # - 设备兼容性分析 # # 使用方法: # ./deploy.sh up # 首次启动(会自动初始化) # ./deploy.sh down # 停止 # ./deploy.sh logs # 查看日志 # # 系统要求: # - Docker 20.10+ # - Docker Compose v2+ # - 最低 4GB 内存,推荐 8GB+ # - 约 20GB 磁盘空间 # # ============================================================================= services: # =========================================================================== # Redis - 缓存与消息队列 # =========================================================================== sentry-redis: image: redis:7-alpine container_name: sentry-redis volumes: - sentry_redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - sentry # =========================================================================== # PostgreSQL - 主数据库 # =========================================================================== sentry-postgres: image: postgres:15-alpine container_name: sentry-postgres environment: POSTGRES_USER: sentry POSTGRES_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} POSTGRES_DB: sentry volumes: - sentry_postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U sentry"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - sentry # =========================================================================== # Kafka + Zookeeper - 事件流处理 # =========================================================================== sentry-zookeeper: image: confluentinc/cp-zookeeper:7.5.0 container_name: sentry-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 volumes: - sentry_zookeeper_data:/var/lib/zookeeper/data - sentry_zookeeper_log:/var/lib/zookeeper/log healthcheck: test: ["CMD", "nc", "-z", "localhost", "2181"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - sentry sentry-kafka: image: confluentinc/cp-kafka:7.5.0 container_name: sentry-kafka depends_on: sentry-zookeeper: condition: service_healthy environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: sentry-zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://sentry-kafka:9092 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" volumes: - sentry_kafka_data:/var/lib/kafka/data healthcheck: test: ["CMD", "kafka-broker-api-versions", "--bootstrap-server", "localhost:9092"] interval: 10s timeout: 10s retries: 5 restart: unless-stopped networks: - sentry # =========================================================================== # ClickHouse - 事件存储(高性能分析) # =========================================================================== sentry-clickhouse: image: clickhouse/clickhouse-server:23.8-alpine container_name: sentry-clickhouse volumes: - sentry_clickhouse_data:/var/lib/clickhouse - ./clickhouse/config.xml:/etc/clickhouse-server/config.d/sentry.xml:ro ulimits: nofile: soft: 262144 hard: 262144 healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost:8123/ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped networks: - sentry # =========================================================================== # Snuba - 事件搜索与聚合 # =========================================================================== sentry-snuba-api: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-api depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: api restart: unless-stopped networks: - sentry sentry-snuba-consumer: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-consumer depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: consumer --storage errors --auto-offset-reset=latest --max-batch-time-ms 750 restart: unless-stopped networks: - sentry sentry-snuba-outcomes-consumer: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-outcomes-consumer depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: consumer --storage outcomes_raw --auto-offset-reset=earliest --max-batch-time-ms 750 restart: unless-stopped networks: - sentry sentry-snuba-sessions-consumer: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-sessions-consumer depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: consumer --storage sessions_raw --auto-offset-reset=latest --max-batch-time-ms 750 restart: unless-stopped networks: - sentry sentry-snuba-transactions-consumer: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-transactions-consumer depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: consumer --storage transactions --auto-offset-reset=latest --max-batch-time-ms 750 restart: unless-stopped networks: - sentry sentry-snuba-replacer: image: getsentry/snuba:24.1.0 container_name: sentry-snuba-replacer depends_on: sentry-redis: condition: service_healthy sentry-clickhouse: condition: service_healthy sentry-kafka: condition: service_healthy environment: SNUBA_SETTINGS: docker CLICKHOUSE_HOST: sentry-clickhouse REDIS_HOST: sentry-redis KAFKA_BROKER_HOST: sentry-kafka command: replacer --storage errors --auto-offset-reset=latest --max-batch-size 3 restart: unless-stopped networks: - sentry # =========================================================================== # Sentry Core Services # =========================================================================== sentry-web: image: getsentry/sentry:24.1.0 container_name: sentry-web depends_on: sentry-redis: condition: service_healthy sentry-postgres: condition: service_healthy sentry-kafka: condition: service_healthy sentry-snuba-api: condition: service_started ports: - "${SENTRY_PORT:-9000}:9000" environment: SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-please_change_this_to_a_random_string_at_least_50_chars} SENTRY_POSTGRES_HOST: sentry-postgres SENTRY_DB_USER: sentry SENTRY_DB_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} SENTRY_REDIS_HOST: sentry-redis SNUBA: http://sentry-snuba-api:1218 SENTRY_KAFKA_HOST: sentry-kafka # 邮件配置(可选) SENTRY_EMAIL_HOST: ${SENTRY_EMAIL_HOST:-} SENTRY_EMAIL_PORT: ${SENTRY_EMAIL_PORT:-587} SENTRY_EMAIL_USER: ${SENTRY_EMAIL_USER:-} SENTRY_EMAIL_PASSWORD: ${SENTRY_EMAIL_PASSWORD:-} SENTRY_EMAIL_USE_TLS: ${SENTRY_EMAIL_USE_TLS:-true} SENTRY_SERVER_EMAIL: ${SENTRY_SERVER_EMAIL:-sentry@localhost} # 系统配置 SENTRY_SINGLE_ORGANIZATION: "true" volumes: - sentry_data:/data - ./sentry.conf.py:/etc/sentry/sentry.conf.py:ro healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:9000/_health/ || exit 1"] interval: 30s timeout: 10s retries: 5 start_period: 60s restart: unless-stopped networks: - sentry sentry-worker: image: getsentry/sentry:24.1.0 container_name: sentry-worker depends_on: sentry-redis: condition: service_healthy sentry-postgres: condition: service_healthy sentry-kafka: condition: service_healthy environment: SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-please_change_this_to_a_random_string_at_least_50_chars} SENTRY_POSTGRES_HOST: sentry-postgres SENTRY_DB_USER: sentry SENTRY_DB_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} SENTRY_REDIS_HOST: sentry-redis SNUBA: http://sentry-snuba-api:1218 SENTRY_KAFKA_HOST: sentry-kafka command: run worker volumes: - sentry_data:/data - ./sentry.conf.py:/etc/sentry/sentry.conf.py:ro restart: unless-stopped networks: - sentry sentry-cron: image: getsentry/sentry:24.1.0 container_name: sentry-cron depends_on: sentry-redis: condition: service_healthy sentry-postgres: condition: service_healthy environment: SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-please_change_this_to_a_random_string_at_least_50_chars} SENTRY_POSTGRES_HOST: sentry-postgres SENTRY_DB_USER: sentry SENTRY_DB_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} SENTRY_REDIS_HOST: sentry-redis SNUBA: http://sentry-snuba-api:1218 SENTRY_KAFKA_HOST: sentry-kafka command: run cron volumes: - sentry_data:/data - ./sentry.conf.py:/etc/sentry/sentry.conf.py:ro restart: unless-stopped networks: - sentry sentry-ingest-consumer: image: getsentry/sentry:24.1.0 container_name: sentry-ingest-consumer depends_on: sentry-redis: condition: service_healthy sentry-postgres: condition: service_healthy sentry-kafka: condition: service_healthy environment: SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-please_change_this_to_a_random_string_at_least_50_chars} SENTRY_POSTGRES_HOST: sentry-postgres SENTRY_DB_USER: sentry SENTRY_DB_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} SENTRY_REDIS_HOST: sentry-redis SNUBA: http://sentry-snuba-api:1218 SENTRY_KAFKA_HOST: sentry-kafka command: run ingest-consumer --all-consumer-types volumes: - sentry_data:/data - ./sentry.conf.py:/etc/sentry/sentry.conf.py:ro restart: unless-stopped networks: - sentry sentry-post-process-forwarder: image: getsentry/sentry:24.1.0 container_name: sentry-post-process-forwarder depends_on: sentry-redis: condition: service_healthy sentry-postgres: condition: service_healthy sentry-kafka: condition: service_healthy environment: SENTRY_SECRET_KEY: ${SENTRY_SECRET_KEY:-please_change_this_to_a_random_string_at_least_50_chars} SENTRY_POSTGRES_HOST: sentry-postgres SENTRY_DB_USER: sentry SENTRY_DB_PASSWORD: ${SENTRY_DB_PASSWORD:-sentry_secret_password} SENTRY_REDIS_HOST: sentry-redis SNUBA: http://sentry-snuba-api:1218 SENTRY_KAFKA_HOST: sentry-kafka command: run post-process-forwarder --commit-batch-size 1 volumes: - sentry_data:/data - ./sentry.conf.py:/etc/sentry/sentry.conf.py:ro restart: unless-stopped networks: - sentry # =========================================================================== # Relay - 事件接收网关 # =========================================================================== sentry-relay: image: getsentry/relay:24.1.0 container_name: sentry-relay depends_on: sentry-web: condition: service_healthy sentry-kafka: condition: service_healthy ports: - "${SENTRY_RELAY_PORT:-3000}:3000" volumes: - ./relay/config.yml:/work/.relay/config.yml:ro - ./relay/credentials.json:/work/.relay/credentials.json:ro restart: unless-stopped networks: - sentry # =========================================================================== # Symbolicator - 符号化服务(崩溃堆栈解析) # =========================================================================== sentry-symbolicator: image: getsentry/symbolicator:24.1.0 container_name: sentry-symbolicator volumes: - sentry_symbolicator_data:/data - ./symbolicator/config.yml:/etc/symbolicator/config.yml:ro command: run -c /etc/symbolicator/config.yml restart: unless-stopped networks: - sentry # ============================================================================= # Volumes # ============================================================================= volumes: sentry_redis_data: driver: local sentry_postgres_data: driver: local sentry_kafka_data: driver: local sentry_zookeeper_data: driver: local sentry_zookeeper_log: driver: local sentry_clickhouse_data: driver: local sentry_data: driver: local sentry_symbolicator_data: driver: local # ============================================================================= # Networks # ============================================================================= networks: sentry: driver: bridge name: sentry