muyu-apiserver/deploy/docker-compose.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

137 lines
3.2 KiB
YAML

services:
mysql:
image: mysql:8.0
container_name: muyu-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: muyu2026
MYSQL_DATABASE: muyu_wms
TZ: Asia/Shanghai
ports:
- "3306:3306"
volumes:
- ./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
- ../data/mysql:/var/lib/mysql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: muyu-redis
restart: always
ports:
- "6379:6379"
volumes:
- ../data/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
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-crm.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
etcd:
image: quay.io/coreos/etcd:v3.5.17
container_name: muyu-etcd
restart: always
command:
- etcd
- --name=default
- --data-dir=/etcd-data
- --listen-client-urls=http://0.0.0.0:2379
- --advertise-client-urls=http://etcd:2379
- --listen-peer-urls=http://0.0.0.0:2380
- --initial-advertise-peer-urls=http://etcd:2380
- --initial-cluster=default=http://etcd:2380
- --initial-cluster-state=new
ports:
- "2379:2379"
healthcheck:
test: ["CMD", "etcdctl", "endpoint", "health"]
interval: 10s
timeout: 5s
retries: 5
system-rpc:
build:
context: ..
dockerfile: deploy/Dockerfile.system
container_name: muyu-system-rpc
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
etcd:
condition: service_healthy
environment:
TZ: Asia/Shanghai
inventory-rpc:
build:
context: ..
dockerfile: deploy/Dockerfile.inventory
container_name: muyu-inventory-rpc
restart: always
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
etcd:
condition: service_healthy
environment:
TZ: Asia/Shanghai
gateway:
build:
context: ..
dockerfile: deploy/Dockerfile.gateway
container_name: muyu-gateway
restart: always
ports:
- "8888:8888"
depends_on:
- system-rpc
- inventory-rpc
- postgres
environment:
TZ: Asia/Shanghai
nginx:
image: nginx:alpine
container_name: muyu-nginx
restart: always
ports:
- "8080:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
- ../../muyu-portal/dist:/usr/share/nginx/html
- ../data/uploads:/usr/share/nginx/uploads
depends_on:
- gateway