178 lines
7.0 KiB
YAML
178 lines
7.0 KiB
YAML
# Unified backend stack: FastAPI + PostgreSQL + MinIO (GPU via NVIDIA Container Toolkit).
|
||
# Deploy from this directory: docker compose up -d --build
|
||
# Client pages (repo root): ../clients/demo-client/start.sh, ../clients/voice-confirmation/start.sh
|
||
services:
|
||
db:
|
||
image: m.daocloud.io/docker.io/library/postgres:16-alpine
|
||
environment:
|
||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||
POSTGRES_DB: ${POSTGRES_DB:-operation_room}
|
||
# Optional: publish PostgreSQL to host for DBA/debug tools (API connects via db:5432 inside compose).
|
||
ports:
|
||
- "${DOCKER_POSTGRES_PUBLISH_PORT:-${POSTGRES_PORT:-45432}}:5432"
|
||
volumes:
|
||
- pgdata:/var/lib/postgresql/data
|
||
restart: unless-stopped
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 20
|
||
start_period: 5s
|
||
|
||
# bluenviron/mediamtx 为 scratch 镜像,仅含 /mediamtx,无 /bin/sh;用 alpine init 种子配置。
|
||
hls-preview-init:
|
||
image: m.daocloud.io/docker.io/library/alpine:3.20
|
||
restart: "no"
|
||
volumes:
|
||
- hls_preview_config:/config
|
||
- ./resources/mediamtx_hls_preview.bootstrap.yml:/seed/mediamtx.yml:ro
|
||
entrypoint: ["/bin/sh", "-c"]
|
||
command:
|
||
- |
|
||
if [ ! -f /config/mediamtx.yml ]; then
|
||
cp /seed/mediamtx.yml /config/mediamtx.yml
|
||
fi
|
||
|
||
mediamtx-hls:
|
||
image: ${MEDIAMTX_DOCKER_IMAGE:-m.daocloud.io/docker.io/bluenviron/mediamtx:latest}
|
||
container_name: orm-mediamtx-hls
|
||
restart: unless-stopped
|
||
command: ["/config/mediamtx.yml"]
|
||
ports:
|
||
- "127.0.0.1:${DEMO_HLS_PREVIEW_PORT:-18888}:8888"
|
||
volumes:
|
||
- hls_preview_config:/config
|
||
depends_on:
|
||
hls-preview-init:
|
||
condition: service_completed_successfully
|
||
|
||
minio:
|
||
image: m.daocloud.io/docker.io/minio/minio:latest
|
||
command: server /data --console-address ":9001"
|
||
environment:
|
||
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
|
||
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
|
||
ports:
|
||
- "${MINIO_PORT:-19000}:9000"
|
||
- "${MINIO_CONSOLE_PORT:-19001}:9001"
|
||
volumes:
|
||
- minio_data:/data
|
||
restart: unless-stopped
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live"]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 10s
|
||
|
||
api:
|
||
build:
|
||
context: .
|
||
dockerfile: Dockerfile
|
||
network: host
|
||
# Match host uid/gid so bind-mounted ./logs (RTSP slices) is readable on the host (VLC, ffplay).
|
||
user: "${HOST_UID:-1000}:${HOST_GID:-1000}"
|
||
group_add:
|
||
- "${DOCKER_GID:-999}"
|
||
gpus: all
|
||
extra_hosts:
|
||
- "host.docker.internal:host-gateway"
|
||
environment:
|
||
HOST_UID: ${HOST_UID:-1000}
|
||
HOST_GID: ${HOST_GID:-1000}
|
||
DOCKER_GID: ${DOCKER_GID:-999}
|
||
HOME: /tmp
|
||
XDG_CACHE_HOME: /tmp
|
||
UV_CACHE_DIR: /tmp/uv-cache
|
||
TORCH_HOME: /app/.cache/torch
|
||
YOLO_CONFIG_DIR: /app/.cache/ultralytics
|
||
# Numeric UID in compose has no passwd entry; PyTorch inductor cache must not call getpass.getuser().
|
||
TORCHINDUCTOR_CACHE_DIR: /tmp/torchinductor-cache
|
||
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
||
POSTGRES_DB: ${POSTGRES_DB:-operation_room}
|
||
POSTGRES_HOST: db
|
||
POSTGRES_PORT: 5432
|
||
CONSUMABLE_CLASSIFIER_IMGSZ: ${CONSUMABLE_CLASSIFIER_IMGSZ:-224}
|
||
CONSUMABLE_CLASSIFIER_DEVICE: ${CONSUMABLE_CLASSIFIER_DEVICE:-}
|
||
CONSUMABLE_CLASSIFIER_TOPK: ${CONSUMABLE_CLASSIFIER_TOPK:-5}
|
||
CONSUMABLE_MIN_CLS_CONFIDENCE: ${CONSUMABLE_MIN_CLS_CONFIDENCE:-0.5}
|
||
CONSUMABLE_VISION_WINDOW_SEC: ${CONSUMABLE_VISION_WINDOW_SEC:-15}
|
||
HAND_DETECTION_WEIGHTS: ${HAND_DETECTION_WEIGHTS:-}
|
||
HAND_DETECTION_IMGSZ: ${HAND_DETECTION_IMGSZ:-640}
|
||
HAND_DETECTION_DEVICE: ${HAND_DETECTION_DEVICE:-}
|
||
VIDEO_DEFAULT_BACKEND: ${VIDEO_DEFAULT_BACKEND:-rtsp}
|
||
VIDEO_RTSP_URL_TEMPLATE: ${VIDEO_RTSP_URL_TEMPLATE:-}
|
||
OR_SITE_CONFIG_JSON_FILE: ${OR_SITE_CONFIG_JSON_FILE:-}
|
||
VIDEO_CAMERA_BACKEND_OVERRIDES_JSON: ${VIDEO_CAMERA_BACKEND_OVERRIDES_JSON:-}
|
||
HIKVISION_SDK_ENABLED: ${HIKVISION_SDK_ENABLED:-false}
|
||
HIKVISION_LIB_DIR: ${HIKVISION_LIB_DIR:-/opt/hikvision/lib}
|
||
HIKVISION_DEVICE_IP: ${HIKVISION_DEVICE_IP:-}
|
||
HIKVISION_USER: ${HIKVISION_USER:-}
|
||
HIKVISION_PASSWORD: ${HIKVISION_PASSWORD:-}
|
||
HIKVISION_PREVIEW_RTSP_TEMPLATE: ${HIKVISION_PREVIEW_RTSP_TEMPLATE:-}
|
||
OPENCV_FFMPEG_CAPTURE_OPTIONS: ${OPENCV_FFMPEG_CAPTURE_OPTIONS:-rtsp_transport;tcp}
|
||
BAIDU_APP_ID: ${BAIDU_APP_ID:-}
|
||
BAIDU_API_KEY: ${BAIDU_API_KEY:-}
|
||
BAIDU_SECRET_KEY: ${BAIDU_SECRET_KEY:-}
|
||
BAIDU_ASR_DEV_PID: ${BAIDU_ASR_DEV_PID:-1537}
|
||
MINIO_ENDPOINT: ${DOCKER_MINIO_ENDPOINT:-minio:9000}
|
||
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
|
||
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
|
||
MINIO_BUCKET: ${MINIO_BUCKET:-operation-room-voice}
|
||
MINIO_SECURE: ${MINIO_SECURE:-false}
|
||
MINIO_REGION: ${MINIO_REGION:-}
|
||
DEMO_CORS_ENABLED: ${DEMO_CORS_ENABLED:-true}
|
||
DEMO_CORS_ORIGINS: ${DEMO_CORS_ORIGINS:-*}
|
||
DEMO_ORCHESTRATOR_ENABLED: ${DEMO_ORCHESTRATOR_ENABLED:-false}
|
||
RTSP_PRIMARY_CAMERA_ID: ${RTSP_PRIMARY_CAMERA_ID:-or-cam-03}
|
||
RTSP_RECORD_ALL_CAMERAS: ${RTSP_RECORD_ALL_CAMERAS:-false}
|
||
RTSP_SEGMENT_DURATION_SEC: ${RTSP_SEGMENT_DURATION_SEC:-120}
|
||
VIDEO_OPEN_TIMEOUT_SEC: ${VIDEO_OPEN_TIMEOUT_SEC:-90}
|
||
APP_LOG_DIR: ${APP_LOG_DIR:-logs/app}
|
||
APP_LOG_FILE_ENABLED: ${APP_LOG_FILE_ENABLED:-true}
|
||
APP_LOG_ROTATION: ${APP_LOG_ROTATION:-7 days}
|
||
APP_LOG_RETENTION: ${APP_LOG_RETENTION:-7 days}
|
||
# api 在 Compose 桥接网内反代 mediamtx-hls:8888;宿主机调试 HLS 仍用 127.0.0.1:18888
|
||
DEMO_HLS_PREVIEW_UPSTREAM: ${DEMO_HLS_PREVIEW_UPSTREAM:-http://mediamtx-hls:8888}
|
||
DEMO_HLS_PREVIEW_CONFIG_DIR: ${DEMO_HLS_PREVIEW_CONFIG_DIR:-/hls-preview-config}
|
||
DEMO_HLS_PREVIEW_CONTAINER_NAME: ${DEMO_HLS_PREVIEW_CONTAINER_NAME:-orm-mediamtx-hls}
|
||
MEDIAMTX_DOCKER_IMAGE: ${MEDIAMTX_DOCKER_IMAGE:-m.daocloud.io/docker.io/bluenviron/mediamtx:latest}
|
||
command: >
|
||
sh -c "mkdir -p /tmp/uv-cache /tmp/torchinductor-cache &&
|
||
uv run --no-sync alembic upgrade head &&
|
||
uv run --no-sync uvicorn main:app --host 0.0.0.0 --port 8000"
|
||
ports:
|
||
- "${API_PORT:-38080}:8000"
|
||
volumes:
|
||
- hls_preview_config:/hls-preview-config
|
||
- ./logs:/app/logs
|
||
- /var/run/docker.sock:/var/run/docker.sock
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
minio:
|
||
condition: service_started
|
||
mediamtx-hls:
|
||
condition: service_started
|
||
restart: unless-stopped
|
||
healthcheck:
|
||
test:
|
||
[
|
||
"CMD",
|
||
"python",
|
||
"-c",
|
||
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)",
|
||
]
|
||
interval: 10s
|
||
timeout: 5s
|
||
retries: 5
|
||
start_period: 20s
|
||
|
||
volumes:
|
||
pgdata:
|
||
minio_data:
|
||
hls_preview_config:
|