# AI Video Assistant 平台 —— docker compose # # 核心服务(默认起):postgres + api + ui # docker compose up -d postgres api # 后端 + 库 # docker compose up -d # 再带上前端 ui → http://localhost:3030 # # 语音对话调试(参考 dograh quick start 的直连方案): # docker compose up -d && make db-seed # 首次需灌种子(凭证+助手) # 浏览器开 http://localhost:3030 → 助手 → 语音预览 # (localhost 是 secure context,麦克风可用;WebRTC 媒体直连 api,WS 信令走 :8000) # # 可选服务(用 profile 推迟到需要时): # docker compose --profile data up -d # + redis / rustfs(后台任务、S3 录音存储) # docker compose --profile remote up -d # + coturn(WebRTC 公网 TURN 穿透) services: # ---- 数据库(api 强依赖,默认起) ---- postgres: image: pgvector/pgvector:pg17 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-postgres}" POSTGRES_DB: postgres ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 3s timeout: 3s retries: 10 networks: [app-network] # ---- 后端引擎(pipecat:WebRTC + WS 双输出) ---- api: build: ./backend # 调试:挂源码 + --reload,改代码即时生效,无需重建镜像 command: uvicorn app:app --host 0.0.0.0 --port 8000 --reload volumes: - ./backend:/app - /app/.venv # 屏蔽宿主机的 venv(容器用镜像内的依赖) - /app/__pycache__ env_file: - path: ./backend/.env required: false environment: # 容器内连库:用服务名 postgres,覆盖 .env 里的 localhost DATABASE_URL: "postgresql+asyncpg://postgres:${POSTGRES_PASSWORD:-postgres}@postgres:5432/postgres" # 3030 = docker ui 宿主端口;3000 = 宿主机裸跑 npm run dev 时的端口 CORS_ORIGINS: "http://localhost:3030,http://127.0.0.1:3030,http://localhost:3000,http://127.0.0.1:3000" ports: - "8000:8000" depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request;urllib.request.urlopen('http://localhost:8000/health')\""] interval: 15s timeout: 5s retries: 5 start_period: 40s networks: [app-network] # ---- 前端(dev 模式,挂源码带 HMR;发布时再做生产构建) ---- ui: image: node:22-slim working_dir: /app command: sh -c "npm install && npm run dev" environment: NEXT_PUBLIC_API_BASE_URL: "http://localhost:8000" volumes: - ./frontend:/app - /app/node_modules ports: # 宿主机用 3030 访问(容器内 next dev 仍监听 3000),避开本地裸跑前端的 3000 - "3030:3000" depends_on: - api networks: [app-network] # ---- 可选(profile: data):后台任务 / 录音存储 ---- redis: image: redis:7 profiles: ["data"] command: ["--requirepass", "redissecret"] ports: - "6379:6379" volumes: - redis_data:/data networks: [app-network] # RustFS:S3 兼容对象存储(MinIO 替代,Rust 实现) # 9000 = S3 API,9001 = Web 控制台。默认账号 rustfsadmin/rustfsadmin。 rustfs: image: rustfs/rustfs:latest profiles: ["data"] environment: RUSTFS_VOLUMES: /data # 单盘单节点(开发够用) RUSTFS_ADDRESS: 0.0.0.0:9000 # S3 API RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001 # 控制台 RUSTFS_CONSOLE_ENABLE: "true" RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: "*" # 凭证:首次初始化后写入数据卷。改 ak/sk 需先清空 rustfs-data 卷再重起。 RUSTFS_ACCESS_KEY: "${S3_ACCESS_KEY:-rustfsadmin}" RUSTFS_SECRET_KEY: "${S3_SECRET_KEY:-rustfsadmin}" ports: - "127.0.0.1:9000:9000" - "127.0.0.1:9001:9001" volumes: - rustfs-data:/data networks: [app-network] # ---- 可选(profile: remote):WebRTC 公网穿透 ---- coturn: image: coturn/coturn:4.8.0 profiles: ["remote"] network_mode: host # TURN 需直接占用 UDP 端口段 command: - -n - --realm=ai-video - --use-auth-secret - --static-auth-secret=${TURN_SECRET:-changeme} - --min-port=49152 - --max-port=49200 # ---- 可选(profile: tls):nginx 反代统一 TLS,局域网 https 调试语音预览 ---- # 起前先生成证书:./deploy/setup-certs.sh(证书落在 deploy/certs/) # docker compose --profile tls up -d # 浏览器 → https://localhost 或 https://<本机IP> nginx: image: nginx:alpine profiles: ["tls"] ports: - "80:80" - "443:443" volumes: # 整份配置当作 nginx.conf 加载(容器内 proxy_pass 用服务名 api/ui) - ./deploy/nginx/ai-video.docker.conf:/etc/nginx/nginx.conf:ro - ./deploy/certs:/etc/nginx/certs:ro depends_on: - api - ui networks: [app-network] volumes: postgres_data: redis_data: rustfs-data: networks: app-network: driver: bridge