muyu-apiserver/deploy/docker-compose.graph.yaml
Chever John 1f4ccfb54e feat: multi-tenant CRM with PostgreSQL graph, tenant isolation, and Casbin RBAC
- JWT claims extended with tenantId; login enforces strict tenant verification
- AuthorityMiddleware: tenant scope check + Casbin path permission + anti-spoofing
- CRM relation API (upstream/downstream one-hop, create/update/history, full graph)
- CrmRepo backed by PostgreSQL with $N placeholders
- gRPC tenant propagation via UnaryClientInterceptor (x-tenant-id metadata)
- All legacy tables (12) gain tenant_id column with indexes
- All model queries inject WHERE tenant_id filter
- Casbin gorm-adapter downgraded to v3.28.0 for v2 compatibility
- GraphSyncWorker (Kafka -> Neo4j) with idempotent MERGE
- Full graph API restricted to admin role only
- Database migrations for MySQL (CRM tables + tenant columns) and PostgreSQL (CRM init)
- Docker Compose: added postgres service to main stack, graph stack with Kafka/Debezium/Neo4j

Made-with: Cursor
2026-03-30 02:53:55 +00:00

121 lines
3.4 KiB
YAML

services:
postgres:
image: postgres:16
container_name: muyu-postgres
restart: always
environment:
POSTGRES_USER: muyu
POSTGRES_PASSWORD: muyu2026
POSTGRES_DB: muyu_crm
TZ: Asia/Shanghai
ports:
- "5432:5432"
volumes:
- ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
- ../data/postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U muyu -d muyu_crm"]
interval: 10s
timeout: 5s
retries: 8
kafka:
image: bitnami/kafka:3.8
container_name: muyu-kafka
restart: always
environment:
- KAFKA_CFG_NODE_ID=1
- KAFKA_CFG_PROCESS_ROLES=broker,controller
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=1@kafka:9093
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_CFG_NUM_PARTITIONS=3
ports:
- "9092:9092"
volumes:
- ../data/kafka:/bitnami/kafka
healthcheck:
test: ["CMD-SHELL", "kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"]
interval: 15s
timeout: 10s
retries: 10
debezium:
image: debezium/connect:2.7
container_name: muyu-debezium
restart: always
depends_on:
postgres:
condition: service_healthy
kafka:
condition: service_healthy
environment:
BOOTSTRAP_SERVERS: kafka:9092
GROUP_ID: 1
CONFIG_STORAGE_TOPIC: debezium_connect_configs
OFFSET_STORAGE_TOPIC: debezium_connect_offsets
STATUS_STORAGE_TOPIC: debezium_connect_statuses
CONNECT_KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter
CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE: "false"
CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE: "false"
ports:
- "8083:8083"
neo4j:
image: neo4j:5.26
container_name: muyu-neo4j
restart: always
environment:
NEO4J_AUTH: neo4j/muyu2026
NEO4J_server_memory_heap_initial__size: 512m
NEO4J_server_memory_heap_max__size: 1024m
NEO4J_server_default__listen__address: 0.0.0.0
ports:
- "7474:7474"
- "7687:7687"
volumes:
- ../data/neo4j/data:/data
- ../data/neo4j/logs:/logs
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:7474 || exit 1"]
interval: 15s
timeout: 10s
retries: 10
graphsync:
build:
context: ..
dockerfile: deploy/Dockerfile.graphsync
container_name: muyu-graphsync
restart: always
depends_on:
kafka:
condition: service_healthy
neo4j:
condition: service_healthy
environment:
KAFKA_BROKERS: kafka:9092
KAFKA_TOPIC: muyu_crm.public.crm_tenant_relationship
KAFKA_GROUP: graphsync
NEO4J_URI: bolt://neo4j:7687
NEO4J_USER: neo4j
NEO4J_PASS: muyu2026
TZ: Asia/Shanghai
kafka-ui:
image: provectuslabs/kafka-ui:latest
container_name: muyu-kafka-ui
restart: always
depends_on:
kafka:
condition: service_healthy
environment:
KAFKA_CLUSTERS_0_NAME: local
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
ports:
- "8086:8080"