docker-compose.yml•6.82 kB
# MCP Tools Service - Production Docker Compose Configuration
# This configuration includes all necessary services for the MCP Tools platform
# with MediaCrawler integration
#
# Note: 'version' is obsolete in Docker Compose v2+ and has been removed
# Usage from project root: cd deploy && docker compose up -d
services:
# PostgreSQL Database - Shared by main service and MediaCrawler
postgres:
image: postgres:16-alpine
container_name: mcp-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-password}
POSTGRES_DB: ${DB_NAME:-mcp_tools_db}
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
TZ: Asia/Shanghai
ports:
- "${DB_PORT:-5432}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-mcp_tools_db}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- mcp-network
# Redis - Shared cache and session storage
redis:
image: redis:7-alpine
container_name: mcp-redis
restart: unless-stopped
environment:
TZ: Asia/Shanghai
command: >
sh -c "
if [ -n '${REDIS_PASSWORD}' ]; then
redis-server --requirepass ${REDIS_PASSWORD} --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
else
redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
fi
"
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- mcp-network
# MediaCrawler Sidecar Service - 常驻爬虫服务(新增)
media-crawler-sidecar:
build:
context: ..
dockerfile: deploy/Dockerfile.sidecar
args:
- BUILDKIT_INLINE_CACHE=1
image: media-crawler-sidecar:latest
container_name: media-crawler-sidecar
restart: unless-stopped
environment:
# Application Settings
APP_ENV: ${APP_ENV:-prod}
PYTHONPATH: /app:/app/media_crawler
PYTHONUNBUFFERED: 1
TZ: Asia/Shanghai
# Database Configuration (共享配置)
DB_HOST: postgres
DB_PORT: 5432
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-password}
DB_NAME: ${DB_NAME:-mcp_tools_db}
# Redis Configuration
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_DB: ${REDIS_DB:-0}
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# Sidecar Service Configuration
SIDECAR_PORT: ${SIDECAR_PORT:-8001}
BROWSER_POOL_SIZE: ${BROWSER_POOL_SIZE:-3}
# Playwright Configuration
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
ports:
- "${SIDECAR_PORT:-8001}:8001" # Sidecar HTTP API
volumes:
# Shared Data Volumes
- ../data:/app/data
- ../logs:/app/logs
- browser_data:/app/browser_data # 共享浏览器数据(Cookie等)
# Configuration Files (read-only)
- ../app/config:/app/app/config:ro
- ../.env:/app/.env:ro
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/health", "||", "exit", "1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 90s # 浏览器池初始化需要更长时间
networks:
- mcp-network
# Resource Limits (爬虫服务需要更多资源)
deploy:
resources:
limits:
cpus: '3'
memory: 4G
reservations:
cpus: '1'
memory: 2G
# MCP Tools Service - Main FastMCP + FastAPI Application
mcp-service:
build:
context: ..
dockerfile: Dockerfile
args:
- BUILDKIT_INLINE_CACHE=1
image: mcp-tools:latest
container_name: mcp-tools-service
restart: unless-stopped
environment:
# Application Settings
APP_ENV: ${APP_ENV:-prod}
APP_DEBUG: ${APP_DEBUG:-false}
APP_PORT: ${APP_PORT:-9090}
PYTHONPATH: /app:/app/media_crawler
PYTHONUNBUFFERED: 1
TZ: Asia/Shanghai
# Database Configuration
DB_HOST: postgres
DB_PORT: 5432
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD:-password}
DB_NAME: ${DB_NAME:-mcp_tools_db}
# Redis Configuration
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_DB: ${REDIS_DB:-0}
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# MediaCrawler Sidecar Connection(新增)
MEDIA_CRAWLER_SIDECAR_URL: http://media-crawler-sidecar:8001
# JWT Configuration (optional)
JWT_SECRET_KEY: ${JWT_SECRET_KEY:-your-secret-key-change-in-production}
ports:
- "${APP_PORT:-9090}:9090" # MCP SSE Service
- "${ADMIN_PORT:-9091}:9091" # Admin Service
volumes:
# Application Data
- ../data:/app/data
- ../logs:/app/logs
# Configuration Files (read-only)
- ../app/config:/app/app/config:ro
- ../.env:/app/.env:ro
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
media-crawler-sidecar:
condition: service_healthy # 依赖边车服务
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9090/health", "||", "exit", "1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- mcp-network
# Resource Limits (主服务资源需求降低)
deploy:
resources:
limits:
cpus: '1.5'
memory: 1.5G
reservations:
cpus: '0.5'
memory: 512M
# Nginx Reverse Proxy (Optional - for production deployment)
nginx:
image: nginx:alpine
container_name: mcp-nginx
restart: unless-stopped
profiles: ["with-nginx"]
environment:
TZ: Asia/Shanghai
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro # SSL certificates (if needed)
- nginx_logs:/var/log/nginx
depends_on:
- mcp-service
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
- mcp-network
volumes:
# Persistent Data Volumes
postgres_data:
driver: local
redis_data:
driver: local
browser_data:
driver: local
nginx_logs:
driver: local
networks:
mcp-network:
driver: bridge
# 让 Docker 自动分配子网,避免冲突