# HSAP — Huaxu Sentinel Active Safety Platform # 平台 + 内置 CVAT 标注引擎(单文件编排) # # 用法: # cp .env.example .env && cp manifests/feishu.env.example manifests/feishu.env # bash scripts/init_after_clone.sh # docker compose up -d --build # # 可选 MinIO: docker compose --profile minio up -d name: hsap x-platform-env: &platform-env AS_DB_HOST: postgres AS_DB_PORT: "5432" AS_DB_USER: as_platform AS_DB_PASSWORD: as_platform AS_DB_NAME: as_platform AS_REDIS_URL: redis://redis:6379/0 AS_JOB_EXECUTOR: worker AS_DEV_AUTH: "true" AS_FORCE_DEV_AUTH: "true" AS_JWT_SECRET: dev-docker-secret AS_FRONTEND_URL: ${AS_FRONTEND_URL:-http://127.0.0.1:8787} FEISHU_REDIRECT_URI: ${FEISHU_REDIRECT_URI:-http://127.0.0.1:8787/api/v1/auth/feishu/callback} AS_WORKSPACE_ROOT: /data/workspace AS_DATA_LAKE_ROOT: /data/data CVAT_HOST: ${CVAT_HOST:-http://hsap-cvat-server:8080} CVAT_PUBLIC_URL: ${CVAT_PUBLIC_URL:-http://127.0.0.1:8080} AS_FLEET_MAP_ENABLED: ${AS_FLEET_MAP_ENABLED:-1} AS_FLEET_MOCK_SEED: ${AS_FLEET_MOCK_SEED:-1} AS_FLEET_MOCK_SIMULATE: ${AS_FLEET_MOCK_SIMULATE:-1} AS_FLEET_SIM_INTERVAL_SEC: ${AS_FLEET_SIM_INTERVAL_SEC:-8} AS_TBOX_INGEST_TOKEN: ${AS_TBOX_INGEST_TOKEN:-hsap-demo-tbox-token} AS_MAP_TILE_PROVIDER: ${AS_MAP_TILE_PROVIDER:-gaode} AS_AMAP_KEY: ${AS_AMAP_KEY:-} x-platform-volumes: &platform-volumes - .:/data/hsap - ${AS_WORKSPACE_ROOT:-./.workspace-stub}:/data/workspace:ro - ${AS_DATA_LAKE_HOST:-../data}:/data/data x-cvat-server-volumes: &cvat-server-volumes - cvat_data:/home/django/data - cvat_keys:/home/django/keys - cvat_logs:/home/django/logs - ${AS_WORKSPACE_ROOT:-./.workspace-stub}:/home/django/share/workspace:ro - ./vendor/cvat/patches/base.py:/home/django/cvat/settings/base.py:ro - ./vendor/cvat/patches/no_auth.py:/home/django/cvat/apps/iam/no_auth.py:ro - ./vendor/cvat/patches/no_auth_middleware.py:/home/django/cvat/apps/iam/no_auth_middleware.py:ro x-cvat-backend-env: &cvat-backend-env CVAT_POSTGRES_HOST: cvat_db CVAT_REDIS_INMEM_HOST: cvat_redis_inmem CVAT_REDIS_INMEM_PORT: 6379 CVAT_REDIS_ONDISK_HOST: cvat_redis_ondisk CVAT_REDIS_ONDISK_PORT: 6666 CLICKHOUSE_HOST: cvat_clickhouse CLICKHOUSE_PORT: 8123 CLICKHOUSE_DB: cvat CLICKHOUSE_USER: user CLICKHOUSE_PASSWORD: user IAM_OPA_URL: http://cvat_opa:8181 CVAT_OPA_URL: http://cvat_opa:8181 CVAT_ANALYTICS: "0" CVAT_ALLOW_STATIC_CACHE: "no" ALLOWED_HOSTS: "*" SMOKESCREEN_OPTS: "" no_proxy: clickhouse,grafana,vector,opa services: postgres: image: postgres:16-alpine container_name: hsap-postgres restart: unless-stopped environment: POSTGRES_USER: as_platform POSTGRES_PASSWORD: as_platform POSTGRES_DB: as_platform ports: - "${AS_DB_PORT:-5432}:5432" volumes: - hsap_pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U as_platform -d as_platform"] interval: 5s timeout: 5s retries: 8 networks: default: aliases: - postgres redis: image: redis:7-alpine container_name: hsap-redis restart: unless-stopped ports: - "${AS_REDIS_PORT:-6379}:6379" volumes: - hsap_redis:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 8 networks: default: aliases: - redis platform: build: context: . dockerfile: Dockerfile container_name: hsap-platform restart: unless-stopped env_file: - path: .env required: false - manifests/feishu.env ports: - "${AS_PLATFORM_PORT:-8787}:8787" environment: <<: *platform-env volumes: *platform-volumes depends_on: postgres: condition: service_healthy redis: condition: service_healthy cvat_traefik: condition: service_started worker: build: context: . dockerfile: Dockerfile container_name: hsap-worker restart: unless-stopped env_file: - path: .env required: false - manifests/feishu.env environment: <<: *platform-env volumes: *platform-volumes command: ["python", "scripts/worker.py"] depends_on: platform: condition: service_started postgres: condition: service_healthy redis: condition: service_healthy # ── CVAT 标注引擎(vendor/cvat/patches:no_auth + HSAP iframe 嵌入)── cvat_db: image: postgres:15-alpine container_name: hsap-cvat-db restart: unless-stopped environment: POSTGRES_USER: root POSTGRES_DB: cvat POSTGRES_HOST_AUTH_METHOD: trust volumes: - cvat_pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U root -d cvat"] interval: 5s timeout: 5s retries: 8 networks: - default cvat_redis_inmem: image: redis:7.2.11-alpine container_name: hsap-cvat-redis-inmem restart: unless-stopped command: ["redis-server", "--save", "60", "100", "--appendonly", "yes"] volumes: - cvat_inmem_db:/data networks: - default cvat_redis_ondisk: image: apache/kvrocks:2.15.0 container_name: hsap-cvat-redis-ondisk restart: unless-stopped init: true volumes: - cvat_cache_db:/var/lib/kvrocks command: ["--compact-cron", "0 3 * * *"] networks: - default cvat_clickhouse: image: clickhouse/clickhouse-server:23.11-alpine container_name: hsap-cvat-clickhouse restart: unless-stopped environment: CLICKHOUSE_DB: cvat CLICKHOUSE_USER: user CLICKHOUSE_PASSWORD: user volumes: - cvat_clickhouse:/var/lib/clickhouse - cvat_clickhouse_logs:/var/log/clickhouse-server networks: default: aliases: - clickhouse cvat_server: image: cvat/server:dev container_name: hsap-cvat-server restart: unless-stopped command: init run server nginx environment: <<: *cvat-backend-env labels: - traefik.enable=true - traefik.http.services.cvat.loadbalancer.server.port=8080 - traefik.http.routers.cvat.rule=PathPrefix(`/api/`)||PathPrefix(`/static/`)||PathPrefix(`/admin`) - traefik.http.routers.cvat.entrypoints=web volumes: *cvat-server-volumes depends_on: cvat_db: condition: service_healthy cvat_clickhouse: condition: service_started networks: default: aliases: - cvat-server cvat_opa: image: openpolicyagent/opa:1.12.2 container_name: hsap-cvat-opa restart: unless-stopped command: - run - --server - --addr=:8181 - --log-level=error - --set=services.cvat.url=http://cvat-server:8080 - --set=bundles.cvat.service=cvat - --set=bundles.cvat.resource=/api/auth/rules - --set=bundles.cvat.polling.min_delay_seconds=5 - --set=bundles.cvat.polling.max_delay_seconds=15 networks: default: aliases: - opa depends_on: - cvat_server cvat_worker_import: image: cvat/server:dev container_name: hsap-cvat-worker-import restart: unless-stopped environment: <<: *cvat-backend-env volumes: *cvat-server-volumes command: run worker import depends_on: - cvat_server networks: - default cvat_worker_export: image: cvat/server:dev container_name: hsap-cvat-worker-export restart: unless-stopped environment: <<: *cvat-backend-env volumes: *cvat-server-volumes command: run worker export depends_on: - cvat_server networks: - default cvat_worker_annotation: image: cvat/server:dev container_name: hsap-cvat-worker-annotation restart: unless-stopped environment: <<: *cvat-backend-env volumes: *cvat-server-volumes command: run worker annotation depends_on: - cvat_server networks: - default cvat_ui: image: cvat/ui:dev container_name: hsap-cvat-ui restart: unless-stopped labels: - traefik.enable=true - traefik.http.services.cvat-ui.loadbalancer.server.port=8000 - traefik.http.routers.cvat-ui.rule=PathPrefix(`/`) - traefik.http.routers.cvat-ui.entrypoints=web - traefik.http.middlewares.cvat-ui-frame.headers.customResponseHeaders.X-Frame-Options= - traefik.http.middlewares.cvat-ui-frame.headers.customResponseHeaders.Content-Security-Policy=frame-ancestors 'self' ${AS_FRONTEND_URL:-http://127.0.0.1:8787} ${CVAT_PUBLIC_URL:-http://127.0.0.1:8080} - traefik.http.routers.cvat-ui.middlewares=cvat-ui-frame depends_on: - cvat_server networks: - default cvat_traefik: image: traefik:v3.6 container_name: hsap-cvat-traefik restart: unless-stopped environment: TRAEFIK_ENTRYPOINTS_web_ADDRESS: :8080 TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "false" TRAEFIK_PROVIDERS_DOCKER_NETWORK: hsap_default ports: - "${CVAT_PORT:-8080}:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro depends_on: - cvat_ui - cvat_server networks: - default # 可选:S3 兼容暂存(联调)— docker compose --profile minio up -d minio: image: minio/minio:latest container_name: hsap-minio profiles: ["minio"] restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin_change_me} ports: - "${MINIO_API_PORT:-9000}:9000" - "${MINIO_CONSOLE_PORT:-9001}:9001" volumes: - hsap_minio_data:/data healthcheck: test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live"] interval: 15s timeout: 5s retries: 5 start_period: 15s minio-init: image: minio/mc:latest container_name: hsap-minio-init profiles: ["minio"] depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin_change_me} MINIO_BUCKET: ${MINIO_BUCKET:-hsap-staging} entrypoint: > /bin/sh -c " mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD && mc mb -p local/$$MINIO_BUCKET || true && mc anonymous set download local/$$MINIO_BUCKET || true " restart: "no" volumes: hsap_pgdata: hsap_redis: hsap_minio_data: cvat_pgdata: name: hsap_cvat_pgdata cvat_inmem_db: name: hsap_cvat_inmem_db cvat_cache_db: name: hsap_cvat_cache_db cvat_clickhouse: cvat_clickhouse_logs: cvat_data: name: hsap_cvat_data cvat_keys: name: hsap_cvat_keys cvat_logs: name: hsap_cvat_logs