| @@ -200,8 +200,19 @@ function Prepare-Package { | |||
| } | |||
| New-Item -ItemType Directory -Force $PackageDir | Out-Null | |||
| Copy-Item (Join-Path $ScriptDir "docker-compose.runtime.yml") (Join-Path $PackageDir "docker-compose.yml") -Force | |||
| Copy-Item (Join-Path $ScriptDir ".env.example") (Join-Path $PackageDir ".env.example") -Force | |||
| $ComposeSource = Join-Path $ScriptDir "docker-compose.runtime.yml" | |||
| $EnvSource = Join-Path $ScriptDir ".env.example" | |||
| $TestComposeSource = Join-Path $ScriptDir "test\docker-compose.yml" | |||
| $TestEnvSource = Join-Path $ScriptDir "test\env.txt" | |||
| if (Test-Path $TestComposeSource) { | |||
| $ComposeSource = $TestComposeSource | |||
| } | |||
| if (Test-Path $TestEnvSource) { | |||
| $EnvSource = $TestEnvSource | |||
| } | |||
| Copy-Item $ComposeSource (Join-Path $PackageDir "docker-compose.yml") -Force | |||
| Copy-Item $EnvSource (Join-Path $PackageDir ".env.example") -Force | |||
| Copy-Item (Join-Path $ScriptDir "install.sh") (Join-Path $PackageDir "install.sh") -Force | |||
| Copy-Item (Join-Path $ScriptDir "README.md") (Join-Path $PackageDir "README.md") -Force | |||
| } | |||
| @@ -150,8 +150,17 @@ prepare_package() { | |||
| rm -rf "$PACKAGE_DIR" | |||
| mkdir -p "$PACKAGE_DIR" | |||
| cp "$SCRIPT_DIR/docker-compose.runtime.yml" "$PACKAGE_DIR/docker-compose.yml" | |||
| cp "$SCRIPT_DIR/.env.example" "$PACKAGE_DIR/.env.example" | |||
| local compose_src="$SCRIPT_DIR/docker-compose.runtime.yml" | |||
| local env_src="$SCRIPT_DIR/.env.example" | |||
| if [[ -f "$SCRIPT_DIR/test/docker-compose.yml" ]]; then | |||
| compose_src="$SCRIPT_DIR/test/docker-compose.yml" | |||
| fi | |||
| if [[ -f "$SCRIPT_DIR/test/env.txt" ]]; then | |||
| env_src="$SCRIPT_DIR/test/env.txt" | |||
| fi | |||
| cp "$compose_src" "$PACKAGE_DIR/docker-compose.yml" | |||
| cp "$env_src" "$PACKAGE_DIR/.env.example" | |||
| cp "$SCRIPT_DIR/install.sh" "$PACKAGE_DIR/install.sh" | |||
| cp "$SCRIPT_DIR/README.md" "$PACKAGE_DIR/README.md" | |||
| @@ -199,4 +208,3 @@ fi | |||
| prepare_package | |||
| save_images | |||
| archive_package | |||
| @@ -0,0 +1,231 @@ | |||
| x-app-env: &app-env | |||
| env_file: | |||
| - .env | |||
| restart: unless-stopped | |||
| networks: | |||
| - emp-net | |||
| x-java-depends: &java-depends | |||
| nacos: | |||
| condition: service_healthy | |||
| mysql: | |||
| condition: service_healthy | |||
| redis: | |||
| condition: service_healthy | |||
| services: | |||
| mysql: | |||
| image: ${MYSQL_IMAGE:-mysql:8.0} | |||
| restart: unless-stopped | |||
| ports: | |||
| - "0.0.0.0:${MYSQL_HOST_PORT:-23306}:3306" | |||
| environment: | |||
| TZ: Asia/Shanghai | |||
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} | |||
| MYSQL_DATABASE: ${MYSQL_DATABASE:-emp} | |||
| command: | |||
| - --character-set-server=utf8mb4 | |||
| - --collation-server=utf8mb4_0900_ai_ci | |||
| - --default-time-zone=+08:00 | |||
| - --max-connections=1000 | |||
| volumes: | |||
| - mysql_data:/var/lib/mysql | |||
| healthcheck: | |||
| test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p\"$${MYSQL_ROOT_PASSWORD}\" --silent"] | |||
| interval: 10s | |||
| timeout: 5s | |||
| retries: 30 | |||
| networks: | |||
| - emp-net | |||
| redis: | |||
| image: ${REDIS_IMAGE:-redis:7-alpine} | |||
| restart: unless-stopped | |||
| environment: | |||
| REDIS_PASSWORD: ${REDIS_PASSWORD} | |||
| command: ["sh", "-c", "redis-server --appendonly yes --requirepass \"$${REDIS_PASSWORD}\""] | |||
| volumes: | |||
| - redis_data:/data | |||
| healthcheck: | |||
| test: ["CMD-SHELL", "redis-cli -a \"$${REDIS_PASSWORD}\" ping | grep -q PONG"] | |||
| interval: 10s | |||
| timeout: 5s | |||
| retries: 30 | |||
| networks: | |||
| - emp-net | |||
| kafka: | |||
| image: ${KAFKA_IMAGE:-bitnami/kafka:3.7.0} | |||
| restart: unless-stopped | |||
| ports: | |||
| - "0.0.0.0:${KAFKA_HOST_PORT:-29362}:9094" | |||
| environment: | |||
| ALLOW_PLAINTEXT_LISTENER: "yes" | |||
| KAFKA_CFG_NODE_ID: 1 | |||
| KAFKA_CFG_PROCESS_ROLES: controller,broker | |||
| KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 | |||
| KAFKA_CFG_LISTENERS: INTERNAL://:9092,CONTROLLER://:9093,EXTERNAL://:9094 | |||
| KAFKA_CFG_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,EXTERNAL://${PUBLIC_HOST}:${KAFKA_HOST_PORT:-29362} | |||
| KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT | |||
| KAFKA_CFG_INTER_BROKER_LISTENER_NAME: INTERNAL | |||
| KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER | |||
| KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE: "true" | |||
| KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 | |||
| KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 | |||
| KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR: 1 | |||
| volumes: | |||
| - kafka_data:/bitnami/kafka | |||
| healthcheck: | |||
| test: ["CMD-SHELL", "/opt/bitnami/kafka/bin/kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --list >/dev/null 2>&1"] | |||
| interval: 10s | |||
| timeout: 5s | |||
| retries: 30 | |||
| networks: | |||
| - emp-net | |||
| kafka-init: | |||
| image: ${KAFKA_IMAGE:-bitnami/kafka:3.7.0} | |||
| restart: "no" | |||
| depends_on: | |||
| kafka: | |||
| condition: service_healthy | |||
| entrypoint: ["/bin/bash", "-ec"] | |||
| environment: | |||
| KAFKA_TOPIC: ${KAFKA_TOPIC:-vehicle-data} | |||
| command: | | |||
| echo "create kafka topic: $${KAFKA_TOPIC}" | |||
| /opt/bitnami/kafka/bin/kafka-topics.sh \ | |||
| --bootstrap-server kafka:9092 \ | |||
| --create \ | |||
| --if-not-exists \ | |||
| --topic "$${KAFKA_TOPIC}" \ | |||
| --partitions 3 \ | |||
| --replication-factor 1 | |||
| /opt/bitnami/kafka/bin/kafka-topics.sh \ | |||
| --bootstrap-server kafka:9092 \ | |||
| --describe \ | |||
| --topic "$${KAFKA_TOPIC}" | |||
| networks: | |||
| - emp-net | |||
| tdengine: | |||
| image: ${TDENGINE_IMAGE:-tdengine/tdengine:3.3.6.0} | |||
| hostname: tdengine | |||
| privileged: true | |||
| restart: unless-stopped | |||
| ports: | |||
| - "0.0.0.0:${TDENGINE_REST_HOST_PORT:-37363}:6041" | |||
| environment: | |||
| TZ: Asia/Shanghai | |||
| TAOS_FQDN: tdengine | |||
| TDENGINE_DATABASE: ${TDENGINE_DATABASE:-emp} | |||
| volumes: | |||
| - tdengine_data:/var/lib/taos | |||
| - tdengine_log:/var/log/taos | |||
| healthcheck: | |||
| test: ["CMD-SHELL", "taos -s \"create database if not exists $${TDENGINE_DATABASE}; show databases;\" >/dev/null 2>&1"] | |||
| interval: 10s | |||
| timeout: 5s | |||
| retries: 30 | |||
| networks: | |||
| - emp-net | |||
| nacos: | |||
| image: ${NACOS_IMAGE:-nacos/nacos-server:v2.3.2-slim} | |||
| restart: unless-stopped | |||
| environment: | |||
| MODE: standalone | |||
| JVM_XMS: 256m | |||
| JVM_XMX: 512m | |||
| SPRING_DATASOURCE_PLATFORM: "" | |||
| NACOS_AUTH_ENABLE: ${NACOS_AUTH_ENABLE:-true} | |||
| NACOS_AUTH_IDENTITY_KEY: ${NACOS_AUTH_IDENTITY_KEY:-emp} | |||
| NACOS_AUTH_IDENTITY_VALUE: ${NACOS_AUTH_IDENTITY_VALUE:-emp2026} | |||
| NACOS_AUTH_TOKEN: ${NACOS_AUTH_TOKEN} | |||
| volumes: | |||
| - nacos_data:/home/nacos/data | |||
| - nacos_logs:/home/nacos/logs | |||
| healthcheck: | |||
| test: ["CMD-SHELL", "curl -sf http://127.0.0.1:8848/nacos/actuator/health || exit 1"] | |||
| interval: 10s | |||
| timeout: 5s | |||
| retries: 30 | |||
| networks: | |||
| - emp-net | |||
| emp-gateway: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-gateway:${IMAGE_TAG:-latest} | |||
| depends_on: | |||
| <<: *java-depends | |||
| emp-auth: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-auth:${IMAGE_TAG:-latest} | |||
| depends_on: | |||
| <<: *java-depends | |||
| emp-monitor: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-monitor:${IMAGE_TAG:-latest} | |||
| depends_on: | |||
| <<: *java-depends | |||
| tdengine: | |||
| condition: service_healthy | |||
| emp-pdf: | |||
| condition: service_started | |||
| emp-data: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-data:${IMAGE_TAG:-latest} | |||
| depends_on: | |||
| <<: *java-depends | |||
| tdengine: | |||
| condition: service_healthy | |||
| kafka-init: | |||
| condition: service_completed_successfully | |||
| emp-ws: | |||
| condition: service_started | |||
| emp-pdf: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-pdf:${IMAGE_TAG:-latest} | |||
| emp-ws: | |||
| <<: *app-env | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-ws:${IMAGE_TAG:-latest} | |||
| ports: | |||
| - "0.0.0.0:${WS_HOST_PORT:-37362}:3000" | |||
| depends_on: | |||
| mysql: | |||
| condition: service_healthy | |||
| redis: | |||
| condition: service_healthy | |||
| kafka-init: | |||
| condition: service_completed_successfully | |||
| emp-admin: | |||
| image: ${IMAGE_NAMESPACE:-emp-test}/emp-admin:${IMAGE_TAG:-latest} | |||
| restart: unless-stopped | |||
| ports: | |||
| - "0.0.0.0:${ADMIN_HOST_PORT:-37361}:80" | |||
| depends_on: | |||
| emp-gateway: | |||
| condition: service_started | |||
| emp-ws: | |||
| condition: service_started | |||
| networks: | |||
| - emp-net | |||
| networks: | |||
| emp-net: | |||
| driver: bridge | |||
| volumes: | |||
| mysql_data: | |||
| redis_data: | |||
| kafka_data: | |||
| tdengine_data: | |||
| tdengine_log: | |||
| nacos_data: | |||
| nacos_logs: | |||
| @@ -0,0 +1,154 @@ | |||
| # EMP 隔离测试环境变量模板 | |||
| # 使用方式:复制为 .env 后按目标服务器实际情况修改。 | |||
| # ----------------------------------------------------------------------------- | |||
| # 镜像与项目名称 | |||
| # ----------------------------------------------------------------------------- | |||
| COMPOSE_PROJECT_NAME=emp-test | |||
| CONTAINER_PREFIX=emp-test | |||
| IMAGE_NAMESPACE=emp-test | |||
| IMAGE_TAG=latest | |||
| # 服务器外网 IP 或域名。 | |||
| # Kafka 对外访问会把这个地址写入 advertised.listeners,外部客户端必须能访问它。 | |||
| PUBLIC_HOST=1.14.103.234 | |||
| # ----------------------------------------------------------------------------- | |||
| # 对外端口 | |||
| # ----------------------------------------------------------------------------- | |||
| # 前端访问:http://PUBLIC_HOST:ADMIN_HOST_PORT | |||
| ADMIN_HOST_PORT=37361 | |||
| GATEWAY_HOST_PORT=9000 | |||
| WS_HOST_PORT=37362 | |||
| PDF_HOST_PORT=3100 | |||
| NACOS_HOST_PORT=9008 | |||
| NACOS_GRPC_HOST_PORT=10008 | |||
| # MySQL / Kafka / TDengine 需要开放到宿主机,便于 Navicat、Kafka 客户端、TDengine Web/REST 调试。 | |||
| # 如果宿主机端口已被其他项目占用,改这里即可。 | |||
| MYSQL_HOST_PORT=23306 | |||
| KAFKA_HOST_PORT=29362 | |||
| TDENGINE_HOST_PORT=6030 | |||
| TDENGINE_REST_HOST_PORT=37363 | |||
| TDENGINE_RPC_HOST_PORT=6043 | |||
| TDENGINE_RPC_UDP_HOST_PORT=6044 | |||
| TDENGINE_KEEPER_HOST_PORT=6060 | |||
| # Redis 默认只绑定本机,避免直接暴露公网;确实需要外部访问再改成 0.0.0.0。 | |||
| REDIS_BIND_HOST=127.0.0.1 | |||
| REDIS_HOST_PORT=16379 | |||
| # ----------------------------------------------------------------------------- | |||
| # 中间件镜像 | |||
| # ----------------------------------------------------------------------------- | |||
| MYSQL_IMAGE=mysql:8.0 | |||
| REDIS_IMAGE=redis:7-alpine | |||
| KAFKA_IMAGE=bitnami/kafka:3.7.0 | |||
| TDENGINE_IMAGE=tdengine/tdengine:3.3.6.0 | |||
| NACOS_IMAGE=nacos/nacos-server:v2.3.2-slim | |||
| # ----------------------------------------------------------------------------- | |||
| # MySQL 8.0 | |||
| # ----------------------------------------------------------------------------- | |||
| MYSQL_DATABASE=emp | |||
| MYSQL_ROOT_PASSWORD=emp_2026_06_01_pwd | |||
| DB_URL=jdbc:mysql://mysql:3306/emp?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai | |||
| DB_USER=root | |||
| DB_PWD=emp_2026_06_01_pwd | |||
| # 给 emp_ws 模拟器读取车辆档案使用。 | |||
| SIMULATOR_DB_HOST=mysql | |||
| SIMULATOR_DB_PORT=3306 | |||
| SIMULATOR_DB_USER=root | |||
| SIMULATOR_DB_PASSWORD=emp_2026_06_01_pwd | |||
| SIMULATOR_DB_DATABASE=emp | |||
| SIMULATOR_DB_LIMIT=0 | |||
| # ----------------------------------------------------------------------------- | |||
| # Redis | |||
| # ----------------------------------------------------------------------------- | |||
| REDIS_HOST=redis | |||
| REDIS_PORT=6379 | |||
| REDIS_PASSWORD=change-me-redis | |||
| REDIS_DB=0 | |||
| # ----------------------------------------------------------------------------- | |||
| # Kafka | |||
| # ----------------------------------------------------------------------------- | |||
| KAFKA_BROKERS=kafka:9092 | |||
| KAFKA_GROUP_ID=ecmp-data-group-v2 | |||
| KAFKA_TOPIC=Yuanjing-vehicle-mock-data | |||
| KAFKA_USER= | |||
| KAFKA_PWD= | |||
| SIMULATOR_KAFKA_BROKERS=kafka:9092 | |||
| SIMULATOR_KAFKA_TOPIC=Yuanjing-vehicle-mock-data | |||
| SIMULATOR_KAFKA_USER= | |||
| SIMULATOR_KAFKA_PASSWORD= | |||
| SIMULATOR_KAFKA_CLIENT_ID=emp-simulator | |||
| SIMULATOR_KAFKA_BATCH_SIZE=500 | |||
| # ----------------------------------------------------------------------------- | |||
| # TDengine | |||
| # ----------------------------------------------------------------------------- | |||
| TDENGINE_DATABASE=emp | |||
| TDENGINE_USER=root | |||
| TDENGINE_PWD=taosdata | |||
| TDENGINE_URL=jdbc:TAOS-RS://tdengine:6041/emp | |||
| # ----------------------------------------------------------------------------- | |||
| # Nacos | |||
| # ----------------------------------------------------------------------------- | |||
| NACOS_ADDR=nacos:8848 | |||
| NACOS_USER=nacos | |||
| NACOS_PWD=nacos | |||
| NACOS_AUTH_ENABLE=true | |||
| NACOS_AUTH_IDENTITY_KEY=emp | |||
| NACOS_AUTH_IDENTITY_VALUE=emp2026 | |||
| NACOS_AUTH_TOKEN=ZW1wLXBsYXRmb3JtLW5hY29zLXNlY3JldC1rZXktMjAyNg== | |||
| # ----------------------------------------------------------------------------- | |||
| # 后端通用配置 | |||
| # ----------------------------------------------------------------------------- | |||
| SPRING_PROFILES_ACTIVE=prod | |||
| JWT_SECRET=emp-platform-secret-key-2026-yjfs | |||
| JWT_EXPIRATION=86400000 | |||
| SCHEDULER_ENABLED=true | |||
| # ----------------------------------------------------------------------------- | |||
| # WebSocket / 模拟器 | |||
| # ----------------------------------------------------------------------------- | |||
| EMP_WS_ENV=production | |||
| NODE_ENV=production | |||
| PORT=3000 | |||
| WS_INSTANCES=1 | |||
| WS_HOST=emp-ws | |||
| SERVER_API_BASE_URL=http://emp-gateway:9000/api | |||
| SIMULATOR_ADMIN_USERNAME=admin | |||
| SIMULATOR_LOGIN_AUTH=88871fe697e860463cd062cf3705b16f | |||
| SIMULATOR_JWT_SECRET=emp-platform-secret-key-2026-yjfs | |||
| # ----------------------------------------------------------------------------- | |||
| # PDF 与前端地址 | |||
| # ----------------------------------------------------------------------------- | |||
| PDF_SERVICE_URL=http://emp-pdf:3100 | |||
| PDF_FRONTEND_BASE_URL=http://1.14.103.234:37361 | |||
| # ----------------------------------------------------------------------------- | |||
| # 第三方配置,按需填写 | |||
| # ----------------------------------------------------------------------------- | |||
| AMAP_KEY= | |||
| COS_SECRET_ID=AKIDynPmvra6PTIsypSr24uXxFKDtPipkUI0 | |||
| COS_SECRET_KEY=Zv76sSq21oPq45vY0GJCuQjrnY6II3aF | |||
| COS_REGION=ap-chengdu | |||
| COS_BUCKET=emp-1258090764 | |||
| SYNC_BASE_URL=https://example.com | |||
| SYNC_TK=change-me | |||
| SYNC_TENANT_ID=2047616403946835969 | |||
| SYNC_REPORT_CRON=0 30 2 * * ? | |||
| SYNC_REPORT_SYNC_ENABLED=false | |||
| SYNC_REPORT_SYNC_CONCURRENCY=3 | |||
| SYNC_REPORT_SYNC_GROUP_NAMES= | |||
| SYNC_REPORT_CACHE_MISS_FETCH_ENABLED=false | |||
| GROUP_REPORT_CRON=0 30 4 ? * THU,SUN | |||