Files
life-echo/api/docker-compose.yml
Kevin 22d282dc01 feat(api): use Tencent 16k_zh_large ASR and remove local Whisper
Standardize ASR on Tencent's dialect-capable engine across all environments,
drop faster-whisper from dependencies and deployment images, and add an
expo-sqlite iOS vendor sync plus pod install in prebuild to prevent native
build failures after npm install.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 10:21:41 +08:00

211 lines
6.2 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
services:
# PostgreSQL 数据库(使用最新版 17
postgres:
image: m.daocloud.io/docker.io/pgvector/pgvector:pg17
container_name: life-echo-postgres
ports:
- "127.0.0.1:${POSTGRES_HOST_PORT:-5432}:5432" # 仅绑定 localhost通过 SSH 隧道访问
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-life_echo}
volumes:
- postgres_data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Redis 服务(业务 key DB/0Celery broker/backend 由应用自动使用 DB/1
redis:
image: m.daocloud.io/docker.io/library/redis:7-alpine
container_name: life-echo-redis
# ports:
# - "6379:6379" # 不暴露到宿主机,仅在 Docker 网络内部访问
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
volumes:
- redis_data:/data
command: >
sh -c 'exec redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
$${REDIS_PASSWORD:+--requirepass "$$REDIS_PASSWORD"}'
restart: always
healthcheck:
test:
[
"CMD-SHELL",
'if [ -n "$$REDIS_PASSWORD" ]; then redis-cli -a "$$REDIS_PASSWORD" ping | grep -q PONG; else redis-cli ping | grep -q PONG; fi',
]
interval: 10s
timeout: 5s
retries: 5
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# FastAPI 应用
# 运行时统一读取 .env部署时在远端将 .env.staging 或 .env.production 复制为 .env。
api:
build:
context: .
dockerfile: Dockerfile
image: life-echo-api:latest
container_name: life-echo-api-prod
# 默认仅绑定本机回环,交给宿主机 Caddy/反代staging 如需 IP:port 直连,可在 .env 设置 LIFE_ECHO_API_HOST_BIND=0.0.0.0。
# 若与 Cosmetic 等共用主机且 8000 已被占用,在 .env 中设置 LIFE_ECHO_API_HOST_PORT=其它端口并在 Caddyfile / app env 中一致。
ports:
- "${LIFE_ECHO_API_HOST_BIND:-127.0.0.1}:${LIFE_ECHO_API_HOST_PORT:-8000}:8000"
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-production}
- REDIS_URL=redis://redis:6379/0
- CELERY_REDIS_URL=redis://redis:6379/1
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
volumes:
- /root/apiclient_key.pem:/app/certs/apiclient_key.pem:ro
restart: always
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "python", "-c", "import http.client; conn = http.client.HTTPConnection('localhost', 8000); conn.request('GET', '/health'); r = conn.getresponse(); exit(0 if r.status == 200 else 1)"]
interval: 15s
timeout: 5s
retries: 6
start_period: 120s
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Celery Worker后台任务处理禁用镜像内置的 8000 端口健康检查,改用 celery inspect ping
celery-worker:
build:
context: .
dockerfile: Dockerfile
image: life-echo-api:latest
container_name: life-echo-celery-worker
command: uv run celery -A app.tasks.celery_app worker --loglevel=info --concurrency=4 -Q celery,memory_idle
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-production}
- REDIS_URL=redis://redis:6379/0
- CELERY_REDIS_URL=redis://redis:6379/1
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
restart: always
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
api:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "uv run celery -A app.tasks.celery_app inspect ping --timeout 10 2>/dev/null | grep -q pong || exit 1"]
interval: 30s
timeout: 15s
retries: 3
start_period: 30s
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
celery-beat:
build:
context: .
dockerfile: Dockerfile
image: life-echo-api:latest
container_name: life-echo-celery-beat
command: uv run celery -A app.tasks.celery_app beat --loglevel=info
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-production}
- REDIS_URL=redis://redis:6379/0
- CELERY_REDIS_URL=redis://redis:6379/1
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
restart: always
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
celery-worker:
condition: service_started
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
flower:
build:
context: .
dockerfile: Dockerfile
image: life-echo-api:latest
container_name: life-echo-flower
command: >
sh -c 'uv run celery -A app.tasks.celery_app flower --port=5555
--basic_auth=$${FLOWER_USER:-admin}:$${FLOWER_PASSWORD:-changeme}'
ports:
- "127.0.0.1:${FLOWER_HOST_PORT:-5555}:5555"
env_file:
- .env
environment:
- APP_ENV=${APP_ENV:-production}
- REDIS_URL=redis://redis:6379/0
- CELERY_REDIS_URL=redis://redis:6379/1
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
- FLOWER_USER=${FLOWER_USER:-admin}
- FLOWER_PASSWORD=${FLOWER_PASSWORD:-changeme}
restart: always
depends_on:
redis:
condition: service_healthy
celery-worker:
condition: service_started
networks:
- life-echo-network
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
networks:
life-echo-network:
external: true
name: api_life-echo-network
volumes:
postgres_data:
driver: local
redis_data:
driver: local