#!/bin/bash # 遇到错误立即退出 set -e # 配置变量 REGISTRY="harbor.3prism.ai" PROJECT="fundamental_analysis" VERSION="latest" NAMESPACE="$REGISTRY/$PROJECT" # 颜色输出 GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # No Color echo -e "${GREEN}=== 开始构建并推送镜像到 $NAMESPACE ===${NC}" # 定义服务列表 # 格式: "服务名:Dockerfile路径" # 注意:所有的后端服务现在都使用通用的 docker/Dockerfile.backend.prod SERVICES=( "data-persistence-service:docker/Dockerfile.backend.prod" "api-gateway:docker/Dockerfile.backend.prod" "alphavantage-provider-service:docker/Dockerfile.backend.prod" "tushare-provider-service:docker/Dockerfile.backend.prod" "finnhub-provider-service:docker/Dockerfile.backend.prod" "yfinance-provider-service:docker/Dockerfile.backend.prod" "report-generator-service:docker/Dockerfile.backend.prod" "workflow-orchestrator-service:docker/Dockerfile.backend.prod" "mock-provider-service:docker/Dockerfile.backend.prod" "frontend:docker/Dockerfile.frontend.prod" ) # 总大小计数器 TOTAL_SIZE=0 for entry in "${SERVICES[@]}"; do KEY="${entry%%:*}" DOCKERFILE="${entry#*:}" IMAGE_NAME="$NAMESPACE/$KEY:$VERSION" echo -e "\n${YELLOW}>>> 正在构建 $KEY ...${NC}" echo "使用 Dockerfile: $DOCKERFILE" # 构建镜像 if [ "$KEY" == "frontend" ]; then # 前端不需要 SERVICE_NAME build-arg docker build -t "$IMAGE_NAME" -f "$DOCKERFILE" . elif [ "$KEY" == "data-persistence-service" ]; then # 特殊处理 data-persistence-service 的二进制名称差异 docker build -t "$IMAGE_NAME" --build-arg SERVICE_NAME="data-persistence-service-server" -f "$DOCKERFILE" . else # 后端服务需要传递 SERVICE_NAME docker build -t "$IMAGE_NAME" --build-arg SERVICE_NAME="$KEY" -f "$DOCKERFILE" . fi # 获取镜像大小 (MB) SIZE_BYTES=$(docker inspect "$IMAGE_NAME" --format='{{.Size}}') SIZE_MB=$(echo "scale=2; $SIZE_BYTES / 1024 / 1024" | bc) echo -e "${GREEN}√ $KEY 构建完成. 大小: ${SIZE_MB} MB${NC}" # 累加大小 TOTAL_SIZE=$(echo "$TOTAL_SIZE + $SIZE_BYTES" | bc) echo -e "${YELLOW}>>> 正在推送 $KEY 到 Harbor ...${NC}" docker push "$IMAGE_NAME" done TOTAL_SIZE_MB=$(echo "scale=2; $TOTAL_SIZE / 1024 / 1024" | bc) echo -e "\n${GREEN}=== 所有镜像处理完成 ===${NC}" echo -e "${GREEN}总大小: ${TOTAL_SIZE_MB} MB${NC}" # 生成服务器使用的 docker-compose.server.yml echo -e "\n${YELLOW}>>> 正在生成服务器部署文件 docker-compose.server.yml ...${NC}" # 基于 docker-compose.prod.yml 生成,但是替换 build 为 image # 这里我们直接手动定义,因为解析 yaml 替换比较复杂,且我们清楚结构 cat > docker-compose.server.yml </dev/null || exit 1"] interval: 10s timeout: 5s retries: 5 networks: - app-network restart: always api-gateway: image: $NAMESPACE/api-gateway:$VERSION container_name: api-gateway environment: SERVER_PORT: 4000 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 REPORT_GENERATOR_SERVICE_URL: http://report-generator-service:8004 RUST_LOG: info,axum=info RUST_BACKTRACE: "1" depends_on: nats: condition: service_started data-persistence-service: condition: service_healthy networks: - app-network healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:4000/health >/dev/null || exit 1"] interval: 10s timeout: 5s retries: 5 restart: always mock-provider-service: image: $NAMESPACE/mock-provider-service:$VERSION container_name: mock-provider-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8006 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: mock-provider-service RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network restart: always alphavantage-provider-service: image: $NAMESPACE/alphavantage-provider-service:$VERSION container_name: alphavantage-provider-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8000 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: alphavantage-provider-service RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network restart: always tushare-provider-service: image: $NAMESPACE/tushare-provider-service:$VERSION container_name: tushare-provider-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8001 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 TUSHARE_API_URL: http://api.waditu.com API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: tushare-provider-service RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network restart: always finnhub-provider-service: image: $NAMESPACE/finnhub-provider-service:$VERSION container_name: finnhub-provider-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8002 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 FINNHUB_API_URL: https://finnhub.io/api/v1 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: finnhub-provider-service RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network restart: always yfinance-provider-service: image: $NAMESPACE/yfinance-provider-service:$VERSION container_name: yfinance-provider-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8003 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 API_GATEWAY_URL: http://api-gateway:4000 WORKFLOW_DATA_PATH: /mnt/workflow_data SERVICE_HOST: yfinance-provider-service RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network dns: - 8.8.8.8 - 8.8.4.4 restart: always report-generator-service: image: $NAMESPACE/report-generator-service:$VERSION container_name: report-generator-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8004 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 GOTENBERG_URL: http://gotenberg:3000 WORKFLOW_DATA_PATH: /mnt/workflow_data RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service - gotenberg networks: - app-network restart: always workflow-orchestrator-service: image: $NAMESPACE/workflow-orchestrator-service:$VERSION container_name: workflow-orchestrator-service volumes: - workflow_data:/mnt/workflow_data environment: SERVER_PORT: 8005 NATS_ADDR: nats://nats:4222 DATA_PERSISTENCE_SERVICE_URL: http://data-persistence-service:3000 WORKFLOW_DATA_PATH: /mnt/workflow_data RUST_LOG: info RUST_BACKTRACE: "1" depends_on: - nats - data-persistence-service networks: - app-network restart: always gotenberg: image: gotenberg/gotenberg:8 container_name: gotenberg networks: - app-network restart: always frontend: image: $NAMESPACE/frontend:$VERSION container_name: fundamental-frontend ports: - "8080:80" # Map host 8080 to container 80 (Nginx) depends_on: api-gateway: condition: service_healthy networks: - app-network restart: always volumes: workflow_data: pgdata: nats_data: networks: app-network: EOF echo -e "${GREEN}生成完成: docker-compose.server.yml${NC}" echo -e "请将此文件复制到远程服务器,并执行: docker-compose -f docker-compose.server.yml up -d"