Fundamental_Analysis/deploy_to_harbor.sh
Lv, Qi fbb1703b00 feat: fix provider test endpoints and update deployment scripts
- Finnhub: Add missing /test endpoint
- AlphaVantage: Fix test endpoint deserialization (handle null api_url)
- Mock Provider: Add /test endpoint and fix Zodios validation error by adding Mock enum
- Deployment: Remove Mock Provider from production deployment script
- Infrastructure: Add production Dockerfiles and compose configs
2025-12-01 02:00:21 +08:00

340 lines
9.8 KiB
Bash

#!/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 <<EOF
services:
postgres-db:
image: timescale/timescaledb:2.15.2-pg16
container_name: fundamental-postgres
command: -c shared_preload_libraries=timescaledb
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: fundamental
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d fundamental"]
interval: 5s
timeout: 5s
retries: 10
networks:
- app-network
restart: always
nats:
image: nats:2.9
container_name: fundamental-nats
volumes:
- nats_data:/data
networks:
- app-network
restart: always
data-persistence-service:
image: $NAMESPACE/data-persistence-service:$VERSION
container_name: data-persistence-service
environment:
HOST: 0.0.0.0
PORT: 3000
DATABASE_URL: postgresql://postgres:postgres@postgres-db:5432/fundamental
RUST_LOG: info
RUST_BACKTRACE: "1"
SKIP_MIGRATIONS_ON_MISMATCH: "1"
depends_on:
postgres-db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:3000/health >/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"