Files
MemeMeow/docker-compose.yml
infstellar 5ecda39843 Add unit tests for image processing worker, operation policy, reverse image provider, and scope handling
- Implement tests for the ImageProcessingWorker to validate task deduplication and policy interactions.
- Create tests for operation policy to ensure proper grant handling and error responses.
- Add tests for reverse image provider response structure to validate empty and malformed results.
- Develop comprehensive tests for scope resolution and service validation to ensure correct behavior in various scenarios.
2026-08-17 12:50:29 +08:00

199 lines
7.9 KiB
YAML
Raw Permalink 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:
postgres:
image: pgvector/pgvector:pg16
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB:-mememeow}
POSTGRES_USER: ${POSTGRES_USER:-mememeow}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mememeow}
ports:
- "127.0.0.1:5434:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 3s
timeout: 3s
retries: 20
volumes:
- mememeow-postgres-data:/var/lib/postgresql/data
db-init:
build:
context: .
depends_on:
postgres:
condition: service_healthy
environment:
MEMEMEOW_DATABASE_URL: ${MEMEMEOW_DATABASE_URL_CONTAINER:-postgresql+psycopg://mememeow:mememeow@postgres:5432/mememeow}
working_dir: /app
command: ["alembic", "upgrade", "head"]
db-viewer:
profiles: ["db-viewer"]
image: adminer:4
depends_on:
postgres:
condition: service_healthy
environment:
ADMINER_DEFAULT_SERVER: postgres
ports:
- "127.0.0.1:${MEMEMEOW_DB_VIEWER_PORT:-8080}:8080"
mememeow-visual:
build:
context: .
dockerfile: docker/visual/Dockerfile
container_name: ${MEMEMEOW_VISUAL_CONTAINER_NAME:-mememeow-visual}
restart: unless-stopped
# 视觉端口只加入 Compose 网络,不发布到宿主机。
expose:
- "8276"
networks:
- visual-backend
environment:
MEMEMEOW_VISUAL_MODEL: ${MEMEMEOW_VISUAL_MODEL:-dinov2_vitb14}
MEMEMEOW_VISUAL_DIMENSIONS: ${MEMEMEOW_VISUAL_DIMENSIONS:-768}
MEMEMEOW_VISUAL_PREPROCESS_VERSION: ${MEMEMEOW_VISUAL_PREPROCESS_VERSION:-dinov2_vitb14-rgb224-first-frame-v1}
MEMEMEOW_VISUAL_MODEL_REPO: /opt/dinov2
MEMEMEOW_VISUAL_WEIGHTS_PATH: /models/dinov2_vitb14_pretrain.pth
MEMEMEOW_VISUAL_WEIGHTS_SHA256: ${MEMEMEOW_VISUAL_WEIGHTS_SHA256:-}
MEMEMEOW_VISUAL_INTERNAL_TOKEN: ${MEMEMEOW_VISUAL_INTERNAL_TOKEN:-}
MEMEMEOW_VISUAL_CPU_THREADS: ${MEMEMEOW_VISUAL_CPU_THREADS:-4}
MEMEMEOW_VISUAL_CPU_INTEROP_THREADS: ${MEMEMEOW_VISUAL_CPU_INTEROP_THREADS:-1}
MEMEMEOW_VISUAL_MAX_PIXELS: ${MEMEMEOW_VISUAL_MAX_PIXELS:-25000000}
volumes:
- type: bind
source: ${MEMEMEOW_VISUAL_WEIGHTS_DIR:-./data/models}
target: /models
read_only: true
bind:
create_host_path: true
- type: bind
source: ./data/images
target: /images
read_only: true
cpus: ${MEMEMEOW_VISUAL_CPU_QUOTA:-4.0}
mem_limit: ${MEMEMEOW_VISUAL_MEMORY_LIMIT:-8g}
healthcheck:
test: ["CMD-SHELL", "python -c 'import json,urllib.request; payload=json.load(urllib.request.urlopen(\"http://127.0.0.1:8276/health\", timeout=3)); raise SystemExit(0 if payload.get(\"status\") in (\"ok\", \"degraded\") else 1)' "]
interval: 15s
timeout: 5s
retries: 3
mememeow-agent-runtime:
build:
context: .
dockerfile: docker/agent/Dockerfile
container_name: ${MEMEMEOW_AGENT_CONTAINER_NAME:-mememeow-agent-runtime}
init: true
restart: unless-stopped
working_dir: /runtime/workspace
expose:
- "8277"
environment:
# token 首次由非 root executor 写入持久 named volume;API 只读同一文件。
MEMEMEOW_AGENT_EXECUTOR_TOKEN_FILE: /run/agent-executor-secret/token
MEMEMEOW_AGENT_EXECUTOR_HOST: 0.0.0.0
MEMEMEOW_AGENT_EXECUTOR_PORT: ${MEMEMEOW_AGENT_EXECUTOR_PORT:-8277}
MEMEMEOW_AGENT_EXECUTOR_MAX_TIMEOUT_SECONDS: ${MEMEMEOW_AGENT_EXECUTOR_MAX_TIMEOUT_SECONDS:-1800}
MEMEMEOW_OPENCODE_EXECUTABLE: opencode
MEMEMEOW_OPENCODE_MODEL: ${MEMEMEOW_OPENCODE_MODEL:-}
MEMEMEOW_OPENCODE_BASE_URL: ${MEMEMEOW_OPENCODE_BASE_URL:-}
MEMEMEOW_OPENCODE_API_KEY: ${MEMEMEOW_OPENCODE_API_KEY:-}
MEMEMEOW_OPENCODE_CONCURRENCY: ${MEMEMEOW_OPENCODE_CONCURRENCY:-1}
MEMEMEOW_AGENT_BACKPRESSURE: ${MEMEMEOW_AGENT_BACKPRESSURE:-32}
MEMEMEOW_AGENT_RESULT_MAX_BYTES: ${MEMEMEOW_AGENT_RESULT_MAX_BYTES:-1048576}
MEMEMEOW_AGENT_REVERSE_IMAGE_INTERNAL_URL: http://mememeow:8275/internal/reverse-image/search
MEMEMEOW_AGENT_VISUAL_SEARCH_INTERNAL_URL: http://mememeow:8275/internal/visual-search/match
volumes:
# named volume 的 owner 从镜像初始化,不会被全新 checkout 的 bind mount 覆盖为 root。
- mememeow-agent-runtime-data:/runtime
- mememeow-agent-executor-secret:/run/agent-executor-secret
- type: bind
source: ./data/images
target: /images
read_only: true
- type: bind
source: ./skills/research-meme-context
target: /skills/research-meme-context
read_only: true
networks:
- default
healthcheck:
test: ["CMD-SHELL", "test \"$$(id -u)\" != 0 && python3 -m executor.probe"]
interval: 5s
timeout: 5s
retries: 12
start_period: 5s
mememeow:
profiles: ["app"]
depends_on:
postgres:
condition: service_healthy
db-init:
condition: service_completed_successfully
mememeow-agent-runtime:
condition: service_healthy
mememeow-visual:
condition: service_healthy
build:
context: .
restart: unless-stopped
command: ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8275"]
ports:
- "127.0.0.1:8275:8275"
# 视觉权重缺失时 API 可以降级提供界面,因此探活只阻断 HTTP 未启动状态。
healthcheck:
test: ["CMD-SHELL", "python -c 'import json,urllib.request; payload=json.load(urllib.request.urlopen(\"http://127.0.0.1:8275/health\", timeout=3)); raise SystemExit(0 if payload.get(\"status\") in (\"ok\", \"degraded\") else 1)' "]
interval: 10s
timeout: 5s
retries: 12
start_period: 15s
env_file:
- path: .env
required: false
environment:
MEMEMEOW_DATABASE_URL: ${MEMEMEOW_DATABASE_URL_CONTAINER:-postgresql+psycopg://mememeow:mememeow@postgres:5432/mememeow}
MEMEMEOW_IMAGE_ROOT: /app/data/images
MEMEMEOW_OPENCODE_RUNTIME_ROOT: /app/data/opencode
MEMEMEOW_AGENT_CONTAINER_NAME: ${MEMEMEOW_AGENT_CONTAINER_NAME:-mememeow-agent-runtime}
MEMEMEOW_AGENT_RUNTIME_MODE: executor
MEMEMEOW_AGENT_EXECUTOR_URL: http://mememeow-agent-runtime:8277
MEMEMEOW_AGENT_EXECUTOR_TOKEN_FILE: /run/agent-executor-secret/token
MEMEMEOW_AGENT_EXECUTOR_REQUEST_TIMEOUT_SECONDS: ${MEMEMEOW_AGENT_EXECUTOR_REQUEST_TIMEOUT_SECONDS:-1810}
MEMEMEOW_AGENT_EXECUTOR_MAX_TIMEOUT_SECONDS: ${MEMEMEOW_AGENT_EXECUTOR_MAX_TIMEOUT_SECONDS:-1800}
MEMEMEOW_AGENT_CALLBACK_SECRET: ${MEMEMEOW_AGENT_CALLBACK_SECRET:-}
MEMEMEOW_AGENT_CALLBACK_VERIFICATION_KEYS: ${MEMEMEOW_AGENT_CALLBACK_VERIFICATION_KEYS:-}
MEMEMEOW_AGENT_REVERSE_IMAGE_INTERNAL_URL: http://mememeow:8275/internal/reverse-image/search
MEMEMEOW_AGENT_VISUAL_SEARCH_INTERNAL_URL: http://mememeow:8275/internal/visual-search/match
MEMEMEOW_REVERSE_IMAGE_INTERNAL_URL: http://mememeow:8275/internal/reverse-image/search
MEMEMEOW_VISUAL_INTERNAL_URL: http://mememeow-visual:8276/internal/visual-embedding
MEMEMEOW_VISUAL_HEALTH_URL: http://mememeow-visual:8276/health
MEMEMEOW_VISUAL_SEARCH_INTERNAL_URL: http://mememeow:8275/internal/visual-search/match
MEMEMEOW_VISUAL_INTERNAL_TOKEN: ${MEMEMEOW_VISUAL_INTERNAL_TOKEN:-}
MEMEMEOW_OPENCODE_MODEL: ${MEMEMEOW_OPENCODE_MODEL:-}
MEMEMEOW_OPENCODE_BASE_URL: ${MEMEMEOW_OPENCODE_BASE_URL:-}
MEMEMEOW_OPENCODE_API_KEY: ${MEMEMEOW_OPENCODE_API_KEY:-}
volumes:
- mememeow-agent-runtime-data:/app/data/opencode
- type: volume
source: mememeow-agent-executor-secret
target: /run/agent-executor-secret
read_only: true
- type: bind
source: ./data/images
target: /app/data/images
networks:
- default
- visual-backend
networks:
visual-backend:
internal: true
volumes:
mememeow-postgres-data:
mememeow-agent-runtime-data:
# token 不落盘到 checkout 或宿主环境,只存在 Docker named volume。
mememeow-agent-executor-secret: