chore: 统一环境配置,支持 .env 快速切换本地/远程基础设施

This commit is contained in:
2026-07-13 14:17:49 +08:00
parent 8c4deb5be4
commit 0bf48fd449
8 changed files with 273 additions and 57 deletions

View File

@@ -1,32 +1,59 @@
# MySQL # ============================================================
# Sino-MCI 通用环境配置模板
#
# 推荐用法:
# cp .env.local .env # 本机开发,连接 localhost 基础设施
# cp .env.remote .env # 本机开发,连接远程基础设施(如 192.168.1.173
#
# 注意:
# 1. .env 文件不会被提交到仓库(已在 .gitignore 中忽略)。
# 2. scripts/local-up.sh 启动 docker-compose 时,会自动把 host 覆盖为容器名,
# 因此无论 .env 中是 localhost 还是远程 IPdocker-compose 内部都能正确互联。
# 3. 若手动执行 docker compose请确保当前 .env 中的 MYSQL_HOST/REDIS_HOST/
# RABBITMQ_HOST 指向可访问地址,或使用 local-up.sh 启动。
# ============================================================
# --------------------------------------------------
# 基础设施端口与账号
# --------------------------------------------------
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=sino_mci MYSQL_DATABASE=sino_mci
MYSQL_USER=root MYSQL_USER=root
MYSQL_PORT=3306
# Redis
REDIS_PORT=6379 REDIS_PORT=6379
# RabbitMQ
RABBITMQ_DEFAULT_USER=guest RABBITMQ_DEFAULT_USER=guest
RABBITMQ_DEFAULT_PASS=guest RABBITMQ_DEFAULT_PASS=guest
RABBITMQ_AMQP_PORT=5672 RABBITMQ_AMQP_PORT=5672
RABBITMQ_MGMT_PORT=15672 RABBITMQ_MGMT_PORT=15672
# SeaweedFS
SEAWEEDFS_MASTER_PORT=9333 SEAWEEDFS_MASTER_PORT=9333
SEAWEEDFS_S3_PORT=8888 SEAWEEDFS_S3_PORT=8888
# Application ports # --------------------------------------------------
# 应用服务端口
# --------------------------------------------------
MCI_SERVER_PORT=8080 MCI_SERVER_PORT=8080
ADMIN_WEB_PORT=80 ADMIN_WEB_PORT=80
CHANNEL_SERVICE_PORT=8000 CHANNEL_SERVICE_PORT=8000
# JVM options for mci-server # --------------------------------------------------
JAVA_OPTS=-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 # Spring Boot / JVM
# --------------------------------------------------
# Spring profile
SPRING_PROFILES_ACTIVE=dev SPRING_PROFILES_ACTIVE=dev
JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
# OpenAI API key (optional) # --------------------------------------------------
OPENAI_API_KEY=your-openai-api-key-here # Channel Service
# --------------------------------------------------
MAX_RETRY=5
BASE_RETRY_DELAY_SECONDS=5
EVENT_RETENTION_DAYS=10
EVENT_PUBLISH_INTERVAL_SECONDS=5
# --------------------------------------------------
# OpenAI可选
# --------------------------------------------------
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com

50
.env.local Normal file
View File

@@ -0,0 +1,50 @@
# ============================================================
# Sino-MCI 本地开发环境(本机启动后端/前端时加载)
# 使用方式cp .env.local .env
# 说明:应用服务连接本机 localhost 上的基础设施
# ============================================================
# 基础设施连接地址
MYSQL_HOST=localhost
REDIS_HOST=localhost
RABBITMQ_HOST=localhost
SEAWEEDFS_HOST=localhost
# 基础设施端口与账号
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=sino_mci
MYSQL_USER=root
REDIS_PORT=6379
RABBITMQ_DEFAULT_USER=guest
RABBITMQ_DEFAULT_PASS=guest
RABBITMQ_AMQP_PORT=5672
RABBITMQ_MGMT_PORT=15672
SEAWEEDFS_MASTER_PORT=9333
SEAWEEDFS_S3_PORT=8888
# 应用服务端口
MCI_SERVER_PORT=8080
ADMIN_WEB_PORT=80
CHANNEL_SERVICE_PORT=8000
# 应用服务地址
MCI_SERVER_URL=http://localhost:8080/msg-platform
VITE_API_BASE_URL=http://localhost:8080
# Spring Boot / JVM
SPRING_PROFILES_ACTIVE=dev
JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
# Channel Service
MAX_RETRY=5
BASE_RETRY_DELAY_SECONDS=5
EVENT_RETENTION_DAYS=10
EVENT_PUBLISH_INTERVAL_SECONDS=5
# OpenAI可选
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com

50
.env.remote Normal file
View File

@@ -0,0 +1,50 @@
# ============================================================
# Sino-MCI 远程基础设施环境(本机启动后端/前端时加载)
# 使用方式cp .env.remote .env
# 说明:只启动本机应用服务,连接远程 MySQL/Redis/RabbitMQ/SeaweedFS
# ============================================================
# 基础设施连接地址
MYSQL_HOST=192.168.1.173
REDIS_HOST=192.168.1.173
RABBITMQ_HOST=192.168.1.173
SEAWEEDFS_HOST=192.168.1.173
# 基础设施端口与账号
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=sino_mci
MYSQL_USER=root
REDIS_PORT=6379
RABBITMQ_DEFAULT_USER=guest
RABBITMQ_DEFAULT_PASS=guest
RABBITMQ_AMQP_PORT=5672
RABBITMQ_MGMT_PORT=15672
SEAWEEDFS_MASTER_PORT=9333
SEAWEEDFS_S3_PORT=8888
# 应用服务端口
MCI_SERVER_PORT=8080
ADMIN_WEB_PORT=80
CHANNEL_SERVICE_PORT=8000
# 应用服务地址
MCI_SERVER_URL=http://192.168.1.173:8080/msg-platform
VITE_API_BASE_URL=http://192.168.1.173:8080
# Spring Boot / JVM
SPRING_PROFILES_ACTIVE=dev
JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
# Channel Service
MAX_RETRY=5
BASE_RETRY_DELAY_SECONDS=5
EVENT_RETENTION_DAYS=10
EVENT_PUBLISH_INTERVAL_SECONDS=5
# OpenAI可选
OPENAI_API_KEY=
OPENAI_BASE_URL=https://api.openai.com

View File

@@ -1,9 +1,13 @@
import { defineConfig } from 'vite' import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import { resolve } from 'path' import { resolve } from 'path'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '')
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://localhost:8080'
return {
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
@@ -11,10 +15,10 @@ export default defineConfig({
}, },
}, },
server: { server: {
port: 5173, port: parseInt(env.VITE_ADMIN_WEB_PORT || '5173', 10),
proxy: { proxy: {
'/msg-platform': { '/msg-platform': {
target: 'http://localhost:8080', target: apiBaseUrl,
changeOrigin: true, changeOrigin: true,
}, },
}, },
@@ -22,4 +26,5 @@ export default defineConfig({
build: { build: {
outDir: 'dist', outDir: 'dist',
}, },
}
}) })

View File

@@ -1,19 +1,19 @@
spring: spring:
datasource: datasource:
url: jdbc:mysql://localhost:3306/sino_mci?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DATABASE:sino_mci}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
username: root username: ${MYSQL_USER:root}
password: root password: ${MYSQL_ROOT_PASSWORD:root}
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
data: data:
redis: redis:
host: localhost host: ${REDIS_HOST:localhost}
port: 6379 port: ${REDIS_PORT:6379}
database: 0 database: 0
rabbitmq: rabbitmq:
host: localhost host: ${RABBITMQ_HOST:localhost}
port: 5672 port: ${RABBITMQ_AMQP_PORT:5672}
username: guest username: ${RABBITMQ_DEFAULT_USER:guest}
password: guest password: ${RABBITMQ_DEFAULT_PASS:guest}
ai: ai:
openai: openai:
api-key: ${OPENAI_API_KEY:} api-key: ${OPENAI_API_KEY:}

View File

@@ -89,15 +89,17 @@ services:
- "${MCI_SERVER_PORT:-8080}:8080" - "${MCI_SERVER_PORT:-8080}:8080"
environment: environment:
- SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-dev} - SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-dev}
- SPRING_DATASOURCE_URL=jdbc:mysql://mci-mysql:3306/${MYSQL_DATABASE:-sino_mci}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true - MYSQL_HOST=${MYSQL_HOST:-mci-mysql}
- SPRING_DATASOURCE_USERNAME=${MYSQL_USER:-root} - MYSQL_PORT=${MYSQL_PORT:-3306}
- SPRING_DATASOURCE_PASSWORD=${MYSQL_ROOT_PASSWORD:-root} - MYSQL_DATABASE=${MYSQL_DATABASE:-sino_mci}
- SPRING_DATA_REDIS_HOST=mci-redis - MYSQL_USER=${MYSQL_USER:-root}
- SPRING_DATA_REDIS_PORT=6379 - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-root}
- SPRING_RABBITMQ_HOST=mci-rabbitmq - REDIS_HOST=${REDIS_HOST:-mci-redis}
- SPRING_RABBITMQ_PORT=5672 - REDIS_PORT=${REDIS_PORT:-6379}
- SPRING_RABBITMQ_USERNAME=${RABBITMQ_DEFAULT_USER:-guest} - RABBITMQ_HOST=${RABBITMQ_HOST:-mci-rabbitmq}
- SPRING_RABBITMQ_PASSWORD=${RABBITMQ_DEFAULT_PASS:-guest} - RABBITMQ_AMQP_PORT=${RABBITMQ_AMQP_PORT:-5672}
- RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER:-guest}
- RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS:-guest}
- JAVA_OPTS=${JAVA_OPTS:--XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0} - JAVA_OPTS=${JAVA_OPTS:--XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0}
- OPENAI_API_KEY=${OPENAI_API_KEY:-} - OPENAI_API_KEY=${OPENAI_API_KEY:-}
networks: networks:
@@ -141,12 +143,12 @@ services:
ports: ports:
- "${CHANNEL_SERVICE_PORT:-8000}:8000" - "${CHANNEL_SERVICE_PORT:-8000}:8000"
environment: environment:
- MCI_SERVER_URL=http://mci-server:8080/msg-platform - MCI_SERVER_URL=${MCI_SERVER_URL:-http://mci-server:8080/msg-platform}
- EVENT_STORE_PATH=/app/data/events.db - EVENT_STORE_PATH=/app/data/events.db
- MAX_RETRY=5 - MAX_RETRY=${MAX_RETRY:-5}
- BASE_RETRY_DELAY_SECONDS=5 - BASE_RETRY_DELAY_SECONDS=${BASE_RETRY_DELAY_SECONDS:-5}
- EVENT_RETENTION_DAYS=10 - EVENT_RETENTION_DAYS=${EVENT_RETENTION_DAYS:-10}
- EVENT_PUBLISH_INTERVAL_SECONDS=5 - EVENT_PUBLISH_INTERVAL_SECONDS=${EVENT_PUBLISH_INTERVAL_SECONDS:-5}
- OPENAI_API_KEY=${OPENAI_API_KEY:-} - OPENAI_API_KEY=${OPENAI_API_KEY:-}
volumes: volumes:
- channel-service-data:/app/data - channel-service-data:/app/data

View File

@@ -17,6 +17,17 @@ MCI_SERVER_PORT=${MCI_SERVER_PORT:-8080}
ADMIN_WEB_PORT=${ADMIN_WEB_PORT:-80} ADMIN_WEB_PORT=${ADMIN_WEB_PORT:-80}
CHANNEL_SERVICE_PORT=${CHANNEL_SERVICE_PORT:-8000} CHANNEL_SERVICE_PORT=${CHANNEL_SERVICE_PORT:-8000}
# Docker Compose 内部连接必须使用容器名,覆盖 .env 中的 host 配置。
# 当用本脚本启动应用服务时,应用与基础设施在同一 Docker 网络。
dc() {
MYSQL_HOST=mci-mysql \
REDIS_HOST=mci-redis \
RABBITMQ_HOST=mci-rabbitmq \
SEAWEEDFS_HOST=mci-seaweedfs \
MCI_SERVER_URL=http://mci-server:8080/msg-platform \
docker compose "$@"
}
WITH_APPS="" WITH_APPS=""
BUILD_FLAG="" BUILD_FLAG=""
INIT_DATA="" INIT_DATA=""
@@ -60,7 +71,7 @@ wait_for_healthy() {
echo "Waiting for $service to become healthy..." echo "Waiting for $service to become healthy..."
while [ "$retry_count" -lt "$max_retries" ]; do while [ "$retry_count" -lt "$max_retries" ]; do
container_name=$(docker compose -p sino-mci --profile infra --profile app ps -q "$service" 2>/dev/null | head -n1 || true) container_name=$(dc -p sino-mci --profile infra --profile app ps -q "$service" 2>/dev/null | head -n1 || true)
if [ -n "$container_name" ]; then if [ -n "$container_name" ]; then
local status local status
@@ -76,7 +87,7 @@ wait_for_healthy() {
done done
echo "$service did not become healthy within $((max_retries * 2)) seconds." echo "$service did not become healthy within $((max_retries * 2)) seconds."
docker compose -p sino-mci --profile infra --profile app logs --tail=50 "$service" dc -p sino-mci --profile infra --profile app logs --tail=50 "$service"
return 1 return 1
} }
@@ -102,7 +113,7 @@ init_database() {
} }
echo "Starting infrastructure services..." echo "Starting infrastructure services..."
docker compose -p sino-mci --profile infra up -d $BUILD_FLAG dc -p sino-mci --profile infra up -d $BUILD_FLAG
wait_for_healthy mysql 60 wait_for_healthy mysql 60
wait_for_healthy redis 30 wait_for_healthy redis 30
@@ -123,7 +134,7 @@ echo "SeaweedFS: http://localhost:${SEAWEEDFS_MASTER_PORT}"
if [ -n "$WITH_APPS" ]; then if [ -n "$WITH_APPS" ]; then
echo "Starting application services..." echo "Starting application services..."
# Include infra profile so that depends_on conditions can resolve. # Include infra profile so that depends_on conditions can resolve.
docker compose -p sino-mci --profile infra --profile app up -d $BUILD_FLAG dc -p sino-mci --profile infra --profile app up -d $BUILD_FLAG
wait_for_healthy mci-server 90 wait_for_healthy mci-server 90
wait_for_healthy channel-service 60 wait_for_healthy channel-service 60

71
scripts/run-local.sh Executable file
View File

@@ -0,0 +1,71 @@
#!/bin/bash
set -euo pipefail
# Sino-MCI 本地开发启动脚本
# 自动加载项目根目录 .env 文件中的环境变量,然后启动后端或前端。
#
# 用法:
# ./scripts/run-local.sh backend
# ./scripts/run-local.sh frontend
# ./scripts/run-local.sh channel
#
# 切换环境:
# cp .env.local .env # 本地基础设施
# cp .env.remote .env # 远程基础设施(如 192.168.1.173
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR/.."
cd "$PROJECT_ROOT"
if [ ! -f .env ]; then
echo ".env file not found. Creating from .env.local ..."
cp .env.local .env
fi
# 加载 .env忽略注释与空行
set -o allexport
# shellcheck source=/dev/null
source .env
set +o allexport
echo "Loaded environment from: $PROJECT_ROOT/.env"
echo " MYSQL_HOST=${MYSQL_HOST:-localhost}"
echo " REDIS_HOST=${REDIS_HOST:-localhost}"
echo " RABBITMQ_HOST=${RABBITMQ_HOST:-localhost}"
echo " MCI_SERVER_URL=${MCI_SERVER_URL:-http://localhost:8080/msg-platform}"
echo " VITE_API_BASE_URL=${VITE_API_BASE_URL:-http://localhost:8080}"
echo ""
SERVICE=${1:-}
if [ -z "$SERVICE" ]; then
echo "Usage: $0 <backend|frontend|channel>"
exit 1
fi
case "$SERVICE" in
backend|server)
cd backend/mci-server
echo "Starting mci-server with Maven..."
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
;;
frontend|web)
cd admin-web
echo "Starting admin-web with Vite..."
npm run dev
;;
channel|channel-service)
cd channel-service
echo "Starting channel-service..."
if [ ! -d .venv ]; then
python3 -m venv .venv
fi
source .venv/bin/activate
pip install -r requirements.txt -q
python -m app.main
;;
*)
echo "Unknown service: $SERVICE"
echo "Usage: $0 <backend|frontend|channel>"
exit 1
;;
esac