| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- services:
- # ──────────────────────────────────────────
- # 1. MySQL 主数据库
- # ──────────────────────────────────────────
- mysql:
- image: mysql:8.0
- container_name: ws-mysql
- restart: unless-stopped
- environment:
- TZ: ${TZ:-Asia/Shanghai}
- MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root_pass_change_me}
- MYSQL_DATABASE: ${MYSQL_DATABASE:-wenshu_platform}
- MYSQL_USER: ${MYSQL_USER:-wenshu}
- MYSQL_PASSWORD: ${MYSQL_PASSWORD:-wenshu_db_pass}
- volumes:
- - ./data/mysql:/var/lib/mysql
- - ./backend/src/main/resources/db/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro
- ports:
- - "3306:3306"
- healthcheck:
- test: ["CMD-SHELL", "mysqladmin ping -h localhost -u$${MYSQL_USER} -p$${MYSQL_PASSWORD} --silent"]
- interval: 10s
- timeout: 5s
- retries: 10
- # ──────────────────────────────────────────
- # 2. Milvus 向量数据库(依赖 etcd + minio)
- # ──────────────────────────────────────────
- milvus-etcd:
- image: quay.io/coreos/etcd:v3.5.18
- container_name: ws-milvus-etcd
- restart: unless-stopped
- environment:
- ETCD_AUTO_COMPACTION_MODE: revision
- ETCD_AUTO_COMPACTION_RETENTION: "1000"
- ETCD_QUOTA_BACKEND_BYTES: "4294967296"
- ETCD_SNAPSHOT_COUNT: "50000"
- volumes:
- - ./data/milvus/etcd:/etcd
- command: >
- etcd
- -advertise-client-urls=http://127.0.0.1:2379
- -listen-client-urls=http://0.0.0.0:2379
- --data-dir=/etcd
- healthcheck:
- test: ["CMD", "etcdctl", "endpoint", "health"]
- interval: 30s
- timeout: 20s
- retries: 3
- milvus-minio:
- image: minio/minio:RELEASE.2023-03-20T20-16-18Z
- container_name: ws-milvus-minio
- restart: unless-stopped
- environment:
- MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
- MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
- volumes:
- - ./data/milvus/minio:/minio_data
- command: minio server /minio_data --console-address ":9001"
- healthcheck:
- test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
- interval: 30s
- timeout: 20s
- retries: 3
- milvus-standalone:
- image: milvusdb/milvus:v2.4.15
- container_name: ws-milvus-standalone
- restart: unless-stopped
- depends_on:
- milvus-etcd:
- condition: service_healthy
- milvus-minio:
- condition: service_healthy
- environment:
- ETCD_ENDPOINTS: milvus-etcd:2379
- MINIO_ADDRESS: milvus-minio:9000
- volumes:
- - ./data/milvus/milvus:/var/lib/milvus
- ports:
- - "19530:19530"
- - "9091:9091"
- command: ["milvus", "run", "standalone"]
- healthcheck:
- test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
- interval: 30s
- timeout: 20s
- retries: 5
- # ──────────────────────────────────────────
- # 3. Apache Polaris(Iceberg REST Catalog)
- # 依赖专属 Postgres
- # ──────────────────────────────────────────
- polaris-postgres:
- image: postgres:16
- container_name: ws-polaris-postgres
- restart: unless-stopped
- environment:
- TZ: ${TZ:-Asia/Shanghai}
- POSTGRES_DB: ${POLARIS_POSTGRES_DB:-polaris}
- POSTGRES_USER: ${POLARIS_POSTGRES_USER:-polaris}
- POSTGRES_PASSWORD: ${POLARIS_POSTGRES_PASSWORD:-polaris_pg_pass}
- volumes:
- - ./data/polaris/postgres:/var/lib/postgresql/data
- healthcheck:
- test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
- interval: 10s
- timeout: 5s
- retries: 10
- polaris:
- image: apache/polaris:1.3.0-incubating
- container_name: ws-polaris
- restart: unless-stopped
- depends_on:
- polaris-postgres:
- condition: service_healthy
- ports:
- - "8181:8181"
- environment:
- POLARIS_PERSISTENCE_TYPE: relational-jdbc
- DROP_WITH_PURGE_ENABLED: ${POLARIS_DROP_WITH_PURGE_ENABLED:-true}
- QUARKUS_DATASOURCE_USERNAME: ${POLARIS_POSTGRES_USER:-polaris}
- QUARKUS_DATASOURCE_PASSWORD: ${POLARIS_POSTGRES_PASSWORD:-polaris_pg_pass}
- QUARKUS_DATASOURCE_JDBC_URL: jdbc:postgresql://polaris-postgres:5432/${POLARIS_POSTGRES_DB:-polaris}
- QUARKUS_HTTP_PORT: 8181
- AWS_ACCESS_KEY_ID: ${OSS_AK:-}
- AWS_SECRET_ACCESS_KEY: ${OSS_SK:-}
- AWS_REGION: ${OSS_REGION:-cn-hangzhou}
- AWS_DEFAULT_REGION: ${OSS_REGION:-cn-hangzhou}
- AWS_REQUEST_CHECKSUM_CALCULATION: WHEN_REQUIRED
- AWS_RESPONSE_CHECKSUM_VALIDATION: WHEN_REQUIRED
- healthcheck:
- test: ["CMD-SHELL", "bash -c '</dev/tcp/localhost/8181' 2>/dev/null && exit 0 || exit 1"]
- interval: 15s
- timeout: 5s
- retries: 20
- start_period: 60s
- # ──────────────────────────────────────────
- # 4. TEI 向量化服务(CPU 模式)
- # ──────────────────────────────────────────
- tei:
- image: ghcr.io/huggingface/text-embeddings-inference:cpu-latest
- container_name: ws-tei
- restart: unless-stopped
- volumes:
- - ./data/huggingface:/data
- ports:
- - "7997:80"
- command: ["--model-id", "${TEI_MODEL_ID:-intfloat/multilingual-e5-base}"]
- healthcheck:
- test: ["CMD", "curl", "-sf", "http://localhost:80/health"]
- interval: 30s
- timeout: 10s
- retries: 10
- start_period: 120s # 首次下载模型需要时间
- # ──────────────────────────────────────────
- # 5. Spring Boot 后端
- # ──────────────────────────────────────────
- backend:
- build:
- context: ./backend
- dockerfile: Dockerfile
- container_name: ws-backend
- restart: unless-stopped
- environment:
- TZ: ${TZ:-Asia/Shanghai}
- MYSQL_URL: ${MYSQL_URL:-mysql:3306}
- MYSQL_DATABASE: ${MYSQL_DATABASE:-wenshu_platform}
- MYSQL_USER: ${MYSQL_USER:-wenshu}
- MYSQL_PASSWORD: ${MYSQL_PASSWORD:-wenshu_db_pass}
- STOCK_SSH_CRYPTO_KEY: ${STOCK_SSH_CRYPTO_KEY:-change-me-stock-ssh-key-32chars}
- SERVER_IP: ${SERVER_IP:-}
- POLARIS_HOST: ${POLARIS_HOST:-}
- POLARIS_REALM: ${POLARIS_REALM:-POLARIS}
- POLARIS_CLIENT_ID: ${POLARIS_CLIENT_ID:-root}
- POLARIS_CLIENT_SECRET: ${POLARIS_CLIENT_SECRET:-s3cr3t}
- POLARIS_DEFAULT_CATALOG: ${POLARIS_DEFAULT_CATALOG:-demo_catalog}
- POLARIS_CACHE_TTL_MINUTES: ${POLARIS_CACHE_TTL_MINUTES:-10}
- KUBEADM_JOIN_COMMAND: ${KUBEADM_JOIN_COMMAND:-}
- OSS_ENDPOINT: ${OSS_ENDPOINT:-https://oss-cn-hangzhou.aliyuncs.com}
- OSS_AK: ${OSS_AK:-}
- OSS_SK: ${OSS_SK:-}
- OSS_REGION: ${OSS_REGION:-cn-hangzhou}
- OSS_BUCKET: ${OSS_BUCKET:-}
- ICEBERG_SERVICE_URL: ${ICEBERG_SERVICE_URL:-http://python-iceberg:8090}
- K8S_ORCHESTRATOR_BASE_URL: ${K8S_ORCHESTRATOR_BASE_URL:-http://ws-orchestrator-api:8080}
- K8S_ORCHESTRATOR_TIMEOUT_MS: ${K8S_ORCHESTRATOR_TIMEOUT_MS:-5000}
- K8S_ORCHESTRATOR_WAIT_TIMEOUT_MS: ${K8S_ORCHESTRATOR_WAIT_TIMEOUT_MS:-300000}
- K8S_ORCHESTRATOR_POLL_INTERVAL_MS: ${K8S_ORCHESTRATOR_POLL_INTERVAL_MS:-2000}
- K8S_ORCHESTRATOR_RECONCILE_CREATE_DELAY_MS: ${K8S_ORCHESTRATOR_RECONCILE_CREATE_DELAY_MS:-5000}
- K8S_ORCHESTRATOR_RECONCILE_BATCH_SIZE: ${K8S_ORCHESTRATOR_RECONCILE_BATCH_SIZE:-100}
- BACKEND_INTERNAL_HEADER: ${BACKEND_INTERNAL_HEADER:-X-Internal-Token}
- BACKEND_INTERNAL_TOKEN: ${BACKEND_INTERNAL_TOKEN:-change-me-internal-token}
- STARROCKS_SQL_RUNNER_USERNAME: ${STARROCKS_SQL_RUNNER_USERNAME:-root}
- STARROCKS_SQL_RUNNER_PASSWORD: ${STARROCKS_SQL_RUNNER_PASSWORD:-}
- STARROCKS_SQL_RUNNER_POLARIS_CATALOG: ${STARROCKS_SQL_RUNNER_POLARIS_CATALOG:-polaris}
- STARROCKS_SQL_RUNNER_QUERY_PORT: ${STARROCKS_SQL_RUNNER_QUERY_PORT:-9030}
- RAG_EMBEDDING_DIMENSION: ${RAG_EMBEDDING_DIMENSION:-768}
- RAG_EMBEDDING_URL: ${RAG_EMBEDDING_URL:-http://tei:80/v1}
- RAG_EMBEDDING_MODEL: ${RAG_EMBEDDING_MODEL:-intfloat/multilingual-e5-base}
- RAG_MILVUS_URI: ${RAG_MILVUS_URI:-http://milvus-standalone:19530}
- RAG_MILVUS_COLLECTION: ${RAG_MILVUS_COLLECTION:-knowledge_vectors}
- RAG_RETRIEVAL_TOP_K: ${RAG_RETRIEVAL_TOP_K:-8}
- RAG_RETRIEVAL_SCORE_THRESHOLD: ${RAG_RETRIEVAL_SCORE_THRESHOLD:-0.3}
- extra_hosts:
- - "host.docker.internal:host-gateway"
- volumes:
- - ./backend/config:/app/config
- depends_on:
- mysql:
- condition: service_healthy
- milvus-standalone:
- condition: service_healthy
- ports:
- - "8080:8080"
- healthcheck:
- test: ["CMD-SHELL", "bash -c '</dev/tcp/localhost/8080' 2>/dev/null && exit 0 || exit 1"]
- interval: 15s
- timeout: 5s
- retries: 20
- start_period: 90s
- # ──────────────────────────────────────────
- # 6. Python Iceberg 服务
- # 启动时会调用 backend 获取配置,必须在 backend 之后启动
- # ──────────────────────────────────────────
- python-iceberg:
- build:
- context: ./python-iceberg
- dockerfile: Dockerfile
- container_name: ws-python-iceberg
- restart: unless-stopped
- depends_on:
- backend:
- condition: service_healthy
- polaris:
- condition: service_healthy
- ports:
- - "8090:8090"
- environment:
- BACKEND_URL: ${ICEBERG_BACKEND_URL:-http://backend:8080}
- BACKEND_INTERNAL_HEADER: ${BACKEND_INTERNAL_HEADER:-X-Internal-Token}
- BACKEND_INTERNAL_TOKEN: ${BACKEND_INTERNAL_TOKEN:-change-me-internal-token}
- # ──────────────────────────────────────────
- # 7. 前端(Nginx)
- # ──────────────────────────────────────────
- frontend:
- build:
- context: ./frontend
- dockerfile: Dockerfile
- container_name: ws-frontend
- restart: unless-stopped
- depends_on:
- - backend
- ports:
- - "80:80"
- # ──────────────────────────────────────────
- # 8. k8s-orchestrator(默认启动,需可访问 K8s API)
- # ──────────────────────────────────────────
- ws-orchestrator-api:
- build:
- context: ./k8s-orchestrator
- dockerfile: Dockerfile.api
- container_name: ws-orchestrator-api
- restart: unless-stopped
- user: "0:0"
- environment:
- TZ: ${TZ:-Asia/Shanghai}
- API_BIND_ADDRESS: ":8080"
- SECRET_NAMESPACE: ${K8S_ORCHESTRATOR_SECRET_NAMESPACE:-orchestrator-system}
- KUBECONFIG: /kube/config
- volumes:
- - ${K8S_KUBECONFIG_PATH:-/root/.kube/config}:/kube/config:ro
- ports:
- - "18080:8080"
- ws-orchestrator-controller:
- build:
- context: ./k8s-orchestrator
- dockerfile: Dockerfile.controller
- container_name: ws-orchestrator-controller
- restart: unless-stopped
- user: "0:0"
- command: ["--leader-elect=false"]
- environment:
- TZ: ${TZ:-Asia/Shanghai}
- KUBECONFIG: /kube/config
- SERVER_IP: ${SERVER_IP:-}
- KUBEADM_JOIN_COMMAND: ${KUBEADM_JOIN_COMMAND:-}
- STARROCKS_BOOTSTRAP_POLARIS_ENABLED: ${STARROCKS_BOOTSTRAP_POLARIS_ENABLED:-true}
- POLARIS_HOST: ${POLARIS_HOST:-}
- POLARIS_CLIENT_ID: ${POLARIS_CLIENT_ID:-root}
- POLARIS_CLIENT_SECRET: ${POLARIS_CLIENT_SECRET:-s3cr3t}
- POLARIS_CATALOG_NAME: ${POLARIS_CATALOG_NAME:-polaris}
- POLARIS_CATALOG_WAREHOUSE: ${POLARIS_CATALOG_WAREHOUSE:-demo_catalog}
- POLARIS_CATALOG_DROP_WITH_PURGE_ENABLED: ${POLARIS_CATALOG_DROP_WITH_PURGE_ENABLED:-true}
- POLARIS_CATALOG_OAUTH2_CREDENTIAL: ${POLARIS_CATALOG_OAUTH2_CREDENTIAL:-}
- POLARIS_CATALOG_OAUTH2_SCOPE: ${POLARIS_CATALOG_OAUTH2_SCOPE:-PRINCIPAL_ROLE:ALL}
- POLARIS_CATALOG_VENDED_CREDENTIALS_ENABLED: ${POLARIS_CATALOG_VENDED_CREDENTIALS_ENABLED:-false}
- STARROCKS_BOOTSTRAP_STORAGE_REGION: ${STARROCKS_BOOTSTRAP_STORAGE_REGION:-${OSS_REGION:-}}
- STARROCKS_BOOTSTRAP_STORAGE_ENDPOINT: ${STARROCKS_BOOTSTRAP_STORAGE_ENDPOINT:-${OSS_ENDPOINT:-}}
- STARROCKS_BOOTSTRAP_STORAGE_ACCESS_KEY: ${STARROCKS_BOOTSTRAP_STORAGE_ACCESS_KEY:-${OSS_AK:-}}
- STARROCKS_BOOTSTRAP_STORAGE_SECRET_KEY: ${STARROCKS_BOOTSTRAP_STORAGE_SECRET_KEY:-${OSS_SK:-}}
- STARROCKS_BOOTSTRAP_STORAGE_PATH_STYLE_ACCESS: ${STARROCKS_BOOTSTRAP_STORAGE_PATH_STYLE_ACCESS:-false}
- volumes:
- - ${K8S_KUBECONFIG_PATH:-/root/.kube/config}:/kube/config:ro
|