修改
This commit is contained in:
@@ -3,24 +3,23 @@
|
|||||||
# 用于统一管理所有服务的启动
|
# 用于统一管理所有服务的启动
|
||||||
# ================================================
|
# ================================================
|
||||||
# 使用方法:
|
# 使用方法:
|
||||||
# 启动所有服务: docker compose up -d
|
# 启动所有服务: docker compose --profile all up -d
|
||||||
# 启动基础设施: docker compose --profile infra up -d
|
# 启动基础设施: docker compose --profile infra up -d
|
||||||
# 启动后端服务: docker compose --profile serv up -d
|
|
||||||
# 启动前端服务: docker compose --profile web up -d
|
|
||||||
# 停止所有服务: docker compose down
|
# 停止所有服务: docker compose down
|
||||||
# 查看日志: docker compose logs -f [service_name]
|
# 查看日志: docker compose logs -f [service_name]
|
||||||
|
#
|
||||||
|
# All-in-One 模式:
|
||||||
|
# - urban-lifeline-serv: 所有后端服务 (单容器)
|
||||||
|
# - urban-lifeline-web: 所有前端应用 (单容器)
|
||||||
|
# - nginx: 反向代理
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
name: urban-lifeline
|
name: urban-lifeline
|
||||||
|
|
||||||
# 引入子目录的 compose 文件
|
# 引入子目录的 compose 文件
|
||||||
include:
|
include:
|
||||||
# Level 1: 基础设施
|
# 基础设施 + 业务服务 (All-in-One)
|
||||||
- path: ./infra/docker-compose.yml
|
- path: ./infra/docker-compose.yml
|
||||||
# Level 2: 后端服务
|
|
||||||
- path: ./urbanLifeline/serv/docker-compose.yml
|
|
||||||
# Level 3: 前端服务
|
|
||||||
- path: ./urbanLifeline/web/docker-compose.yml
|
|
||||||
|
|
||||||
# 共享网络定义
|
# 共享网络定义
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
services:
|
services:
|
||||||
# ====================== Nginx 反向代理 ======================
|
# ====================== Nginx 反向代理 ======================
|
||||||
nginx:
|
nginx:
|
||||||
image: urban-lifeline-web:${IMAGE_VERSION:-latest}
|
image: nginx:alpine
|
||||||
container_name: urban-lifeline-nginx
|
container_name: urban-lifeline-nginx
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
profiles: ["infra", "all"]
|
profiles: ["infra", "all"]
|
||||||
@@ -23,6 +23,9 @@ services:
|
|||||||
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
||||||
# SSL 证书(可选)
|
# SSL 证书(可选)
|
||||||
# - ./nginx/ssl:/etc/nginx/ssl:ro
|
# - ./nginx/ssl:/etc/nginx/ssl:ro
|
||||||
|
depends_on:
|
||||||
|
- urban-lifeline-serv
|
||||||
|
- urban-lifeline-web
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -30,6 +33,73 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
start_period: 30s
|
start_period: 30s
|
||||||
|
|
||||||
|
# ====================== 后端服务 All-in-One ======================
|
||||||
|
urban-lifeline-serv:
|
||||||
|
image: urban-lifeline-serv:${IMAGE_VERSION:-latest}
|
||||||
|
container_name: urban-lifeline-serv
|
||||||
|
restart: unless-stopped
|
||||||
|
profiles: ["infra", "serv", "all"]
|
||||||
|
networks:
|
||||||
|
- urban-lifeline
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
- "8081"
|
||||||
|
- "8082"
|
||||||
|
- "8083"
|
||||||
|
- "8084"
|
||||||
|
- "8085"
|
||||||
|
- "8086"
|
||||||
|
- "8087"
|
||||||
|
- "8088"
|
||||||
|
- "8089"
|
||||||
|
- "8090"
|
||||||
|
environment:
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
||||||
|
NACOS_SERVER_ADDR: nacos:8848
|
||||||
|
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
||||||
|
volumes:
|
||||||
|
- ${DATA_ROOT:-../volumes}/logs/serv:/app/logs
|
||||||
|
depends_on:
|
||||||
|
nacos:
|
||||||
|
condition: service_healthy
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 180s
|
||||||
|
|
||||||
|
# ====================== 前端服务 All-in-One ======================
|
||||||
|
urban-lifeline-web:
|
||||||
|
image: urban-lifeline-web:${IMAGE_VERSION:-latest}
|
||||||
|
container_name: urban-lifeline-web
|
||||||
|
restart: unless-stopped
|
||||||
|
profiles: ["infra", "web", "all"]
|
||||||
|
networks:
|
||||||
|
- urban-lifeline
|
||||||
|
expose:
|
||||||
|
- "8000"
|
||||||
|
- "8001"
|
||||||
|
- "8002"
|
||||||
|
- "8003"
|
||||||
|
- "8004"
|
||||||
|
environment:
|
||||||
|
TZ: Asia/Shanghai
|
||||||
|
SHARED_PORT: 8000
|
||||||
|
PLATFORM_PORT: 8001
|
||||||
|
WORKCASE_PORT: 8002
|
||||||
|
BIDDING_PORT: 8003
|
||||||
|
WORKCASE_WECHAT_PORT: 8004
|
||||||
|
volumes:
|
||||||
|
- ${DATA_ROOT:-../volumes}/logs/web:/app/logs
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
# ====================== Nacos 注册中心 ======================
|
# ====================== Nacos 注册中心 ======================
|
||||||
nacos:
|
nacos:
|
||||||
image: nacos/nacos-server:v3.1.0
|
image: nacos/nacos-server:v3.1.0
|
||||||
|
|||||||
@@ -1,19 +1,32 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
# Urban Lifeline - 站点配置
|
# Urban Lifeline - 站点配置 (All-in-One 模式)
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
# 上游服务定义
|
# 上游服务定义 - 后端 All-in-One 容器
|
||||||
upstream gateway {
|
upstream gateway {
|
||||||
server gateway:8080;
|
server urban-lifeline-serv:8080;
|
||||||
keepalive 32;
|
keepalive 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 上游服务定义 - 前端 All-in-One 容器
|
||||||
|
upstream shared {
|
||||||
|
server urban-lifeline-web:8000;
|
||||||
|
}
|
||||||
|
|
||||||
upstream platform {
|
upstream platform {
|
||||||
server platform:80;
|
server urban-lifeline-web:8001;
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream workcase-web {
|
upstream workcase-web {
|
||||||
server workcase-web:80;
|
server urban-lifeline-web:8002;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream bidding-web {
|
||||||
|
server urban-lifeline-web:8003;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream workcase-wechat {
|
||||||
|
server urban-lifeline-web:8004;
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
@@ -29,6 +42,21 @@ server {
|
|||||||
|
|
||||||
# ====================== 前端应用代理 ======================
|
# ====================== 前端应用代理 ======================
|
||||||
|
|
||||||
|
# Shared 公共模块 (Module Federation 远程模块)
|
||||||
|
location /shared/ {
|
||||||
|
proxy_pass http://shared/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# 允许跨域 (Module Federation 需要)
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
add_header Access-Control-Allow-Methods "GET, OPTIONS";
|
||||||
|
add_header Access-Control-Allow-Headers "Origin, Content-Type, Accept";
|
||||||
|
}
|
||||||
|
|
||||||
# Platform 管理平台
|
# Platform 管理平台
|
||||||
location /platform/ {
|
location /platform/ {
|
||||||
proxy_pass http://platform/;
|
proxy_pass http://platform/;
|
||||||
@@ -39,7 +67,7 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Workcase 工单系统
|
# Workcase 工单系统 PC端
|
||||||
location /workcase/ {
|
location /workcase/ {
|
||||||
proxy_pass http://workcase-web/;
|
proxy_pass http://workcase-web/;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
@@ -49,6 +77,26 @@ server {
|
|||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Bidding 招标系统
|
||||||
|
location /bidding/ {
|
||||||
|
proxy_pass http://bidding-web/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Workcase 工单系统微信端
|
||||||
|
location /workcase-wechat/ {
|
||||||
|
proxy_pass http://workcase-wechat/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
# 默认首页(重定向到 platform)
|
# 默认首页(重定向到 platform)
|
||||||
location = / {
|
location = / {
|
||||||
return 302 /platform/;
|
return 302 /platform/;
|
||||||
|
|||||||
33
docker/urbanLifeline/.env.example
Normal file
33
docker/urbanLifeline/.env.example
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - Docker 环境变量配置
|
||||||
|
# 复制此文件为 .env 并修改配置
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
# 镜像版本
|
||||||
|
IMAGE_VERSION=latest
|
||||||
|
|
||||||
|
# Spring 运行环境
|
||||||
|
SPRING_PROFILES_ACTIVE=prod
|
||||||
|
|
||||||
|
# Nacos 配置
|
||||||
|
NACOS_SERVER_ADDR=nacos:8848
|
||||||
|
NACOS_NAMESPACE=
|
||||||
|
|
||||||
|
# MinIO 配置
|
||||||
|
MINIO_ENDPOINT=http://minio:9000
|
||||||
|
|
||||||
|
# Dify AI 配置
|
||||||
|
DIFY_API_URL=http://dify-api:5001
|
||||||
|
|
||||||
|
# 日志目录
|
||||||
|
LOG_ROOT=../../volumes/logs
|
||||||
|
|
||||||
|
# 前端 API 地址
|
||||||
|
API_BASE_URL=http://gateway:8080
|
||||||
|
|
||||||
|
# 端口映射
|
||||||
|
GATEWAY_PORT=8080
|
||||||
|
PLATFORM_PORT=8001
|
||||||
|
WORKCASE_PORT=8002
|
||||||
|
BIDDING_WEB_PORT=8003
|
||||||
|
WORKCASE_WECHAT_PORT=8004
|
||||||
79
docker/urbanLifeline/Makefile
Normal file
79
docker/urbanLifeline/Makefile
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - Docker 构建与部署 (All-in-One)
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
.PHONY: help build build-serv build-web up down logs ps status restart
|
||||||
|
|
||||||
|
# 默认目标
|
||||||
|
help:
|
||||||
|
@echo "Urban Lifeline Docker 命令 (All-in-One 模式)"
|
||||||
|
@echo ""
|
||||||
|
@echo "构建命令:"
|
||||||
|
@echo " make build - 构建所有镜像"
|
||||||
|
@echo " make build-serv - 构建后端镜像"
|
||||||
|
@echo " make build-web - 构建前端镜像"
|
||||||
|
@echo ""
|
||||||
|
@echo "启动/停止:"
|
||||||
|
@echo " make up - 启动所有服务"
|
||||||
|
@echo " make down - 停止所有服务"
|
||||||
|
@echo ""
|
||||||
|
@echo "管理命令:"
|
||||||
|
@echo " make ps - 查看容器状态"
|
||||||
|
@echo " make status - 查看服务状态"
|
||||||
|
@echo " make logs - 查看日志"
|
||||||
|
@echo " make restart-serv SERVICE=gateway - 重启后端服务"
|
||||||
|
@echo " make restart-web SITE=platform - 重启前端站点"
|
||||||
|
|
||||||
|
# 构建
|
||||||
|
build: build-serv build-web
|
||||||
|
|
||||||
|
build-serv:
|
||||||
|
bash serv/build.sh
|
||||||
|
|
||||||
|
build-web:
|
||||||
|
bash web/build.sh
|
||||||
|
|
||||||
|
# 启动/停止 (通过主 docker-compose)
|
||||||
|
up:
|
||||||
|
cd .. && docker compose --profile all up -d
|
||||||
|
|
||||||
|
down:
|
||||||
|
cd .. && docker compose --profile all down
|
||||||
|
|
||||||
|
# 状态
|
||||||
|
ps:
|
||||||
|
docker ps --filter "name=urban-lifeline"
|
||||||
|
|
||||||
|
status:
|
||||||
|
@echo "=== 后端服务状态 ==="
|
||||||
|
@docker exec urban-lifeline-serv /app/service-manager.sh status 2>/dev/null || echo "后端容器未运行"
|
||||||
|
@echo ""
|
||||||
|
@echo "=== 前端服务状态 ==="
|
||||||
|
@docker exec urban-lifeline-web /app/web-manager.sh status 2>/dev/null || echo "前端容器未运行"
|
||||||
|
|
||||||
|
# 日志
|
||||||
|
logs:
|
||||||
|
cd .. && docker compose logs -f --tail=100
|
||||||
|
|
||||||
|
logs-serv:
|
||||||
|
docker logs -f --tail=100 urban-lifeline-serv
|
||||||
|
|
||||||
|
logs-web:
|
||||||
|
docker logs -f --tail=100 urban-lifeline-web
|
||||||
|
|
||||||
|
# 重启单个服务
|
||||||
|
restart-serv:
|
||||||
|
@if [ -z "$(SERVICE)" ]; then \
|
||||||
|
echo "用法: make restart-serv SERVICE=gateway"; \
|
||||||
|
echo "可用服务: gateway system auth file log message crontab bidding workcase platform ai"; \
|
||||||
|
else \
|
||||||
|
docker exec urban-lifeline-serv /app/service-manager.sh restart $(SERVICE); \
|
||||||
|
fi
|
||||||
|
|
||||||
|
restart-web:
|
||||||
|
@if [ -z "$(SITE)" ]; then \
|
||||||
|
echo "用法: make restart-web SITE=platform"; \
|
||||||
|
echo "可用站点: shared platform workcase bidding workcase_wechat"; \
|
||||||
|
else \
|
||||||
|
docker exec urban-lifeline-web /app/web-manager.sh restart $(SITE); \
|
||||||
|
fi
|
||||||
100
docker/urbanLifeline/README.md
Normal file
100
docker/urbanLifeline/README.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Urban Lifeline Docker 部署
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
docker/urbanLifeline/
|
||||||
|
├── .env.example # 环境变量示例
|
||||||
|
├── README.md # 本文档
|
||||||
|
├── serv/ # 后端服务
|
||||||
|
│ ├── docker-compose.yml
|
||||||
|
│ ├── build.sh # 构建脚本
|
||||||
|
│ ├── start.sh # 启动脚本
|
||||||
|
│ ├── Dockerfile.base # 基础镜像
|
||||||
|
│ ├── Dockerfile.template # 服务模板
|
||||||
|
│ └── Dockerfile.* # 各服务 Dockerfile
|
||||||
|
└── web/ # 前端应用
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── build.sh # 构建脚本
|
||||||
|
├── nginx.conf # Nginx 配置
|
||||||
|
└── Dockerfile.* # 各前端 Dockerfile
|
||||||
|
```
|
||||||
|
|
||||||
|
## 服务端口
|
||||||
|
|
||||||
|
### 后端服务
|
||||||
|
| 服务 | 端口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| gateway | 8080 | API 网关 |
|
||||||
|
| auth | 8081 | 认证服务 |
|
||||||
|
| system | 8082 | 系统服务 |
|
||||||
|
| log | 8083 | 日志服务 |
|
||||||
|
| file | 8084 | 文件服务 |
|
||||||
|
| message | 8085 | 消息服务 |
|
||||||
|
| crontab | 8086 | 定时任务 |
|
||||||
|
| bidding | 8087 | 招标服务 |
|
||||||
|
| workcase | 8088 | 工单服务 |
|
||||||
|
| platform | 8089 | 平台服务 |
|
||||||
|
| ai | 8090 | AI 服务 |
|
||||||
|
|
||||||
|
### 前端应用
|
||||||
|
| 应用 | 端口 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| platform | 8001 | 管理平台 |
|
||||||
|
| workcase-web | 8002 | 工单系统 PC |
|
||||||
|
| bidding-web | 8003 | 招标系统 |
|
||||||
|
| workcase-wechat | 8004 | 工单微信端 |
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 准备环境变量
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
# 编辑 .env 配置
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 构建后端
|
||||||
|
```bash
|
||||||
|
# 先编译 Java 项目
|
||||||
|
cd urbanLifelineServ
|
||||||
|
mvn clean package -DskipTests
|
||||||
|
|
||||||
|
# 构建 Docker 镜像
|
||||||
|
cd docker/urbanLifeline/serv
|
||||||
|
./build.sh # 构建所有
|
||||||
|
./build.sh gateway # 构建单个
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 构建前端
|
||||||
|
```bash
|
||||||
|
# 先构建前端项目
|
||||||
|
cd urbanLifelineWeb
|
||||||
|
pnpm install
|
||||||
|
pnpm build
|
||||||
|
|
||||||
|
# 构建 Docker 镜像
|
||||||
|
cd docker/urbanLifeline/web
|
||||||
|
./build.sh # 构建所有
|
||||||
|
./build.sh platform # 构建单个
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 启动服务
|
||||||
|
```bash
|
||||||
|
# 启动后端
|
||||||
|
cd docker/urbanLifeline/serv
|
||||||
|
docker-compose --profile serv up -d
|
||||||
|
|
||||||
|
# 启动前端
|
||||||
|
cd docker/urbanLifeline/web
|
||||||
|
docker-compose --profile web up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## 依赖服务
|
||||||
|
|
||||||
|
确保以下基础设施服务已启动:
|
||||||
|
- Nacos (服务注册/配置中心)
|
||||||
|
- PostgreSQL (数据库)
|
||||||
|
- Redis (缓存)
|
||||||
|
- MinIO (对象存储)
|
||||||
|
|
||||||
|
可通过 `docker/infra` 目录启动基础设施。
|
||||||
0
docker/urbanLifeline/serv/Dockerfile.serv
Normal file
0
docker/urbanLifeline/serv/Dockerfile.serv
Normal file
@@ -1,45 +0,0 @@
|
|||||||
# ================================================
|
|
||||||
# Urban Lifeline - 微服务 Dockerfile 模板
|
|
||||||
# 用于构建各个后端微服务镜像
|
|
||||||
#
|
|
||||||
# 构建参数:
|
|
||||||
# SERVICE_NAME - 服务名称 (gateway/system/auth/file/ai/workcase)
|
|
||||||
# SERVICE_PORT - 服务端口
|
|
||||||
#
|
|
||||||
# 构建命令示例:
|
|
||||||
# docker build -t urban-lifeline-gateway:latest \
|
|
||||||
# --build-arg SERVICE_NAME=gateway \
|
|
||||||
# --build-arg SERVICE_PORT=8080 \
|
|
||||||
# -f Dockerfile.template .
|
|
||||||
# ================================================
|
|
||||||
FROM urban-lifeline-base-serv:latest
|
|
||||||
|
|
||||||
# 构建参数
|
|
||||||
ARG SERVICE_NAME
|
|
||||||
ARG SERVICE_PORT=8080
|
|
||||||
|
|
||||||
# 环境变量
|
|
||||||
ENV SERVICE_NAME=${SERVICE_NAME} \
|
|
||||||
SERVICE_PORT=${SERVICE_PORT} \
|
|
||||||
SPRING_PROFILES_ACTIVE=prod \
|
|
||||||
JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"
|
|
||||||
|
|
||||||
# 设置工作目录
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# 1. 复制启动脚本(不常变化)
|
|
||||||
COPY docker/urbanLifeline/serv/start.sh /app/start.sh
|
|
||||||
RUN chmod +x /app/start.sh
|
|
||||||
|
|
||||||
# 2. 复制 JAR 包(最常变化,放最后)
|
|
||||||
COPY urbanLifelineServ/${SERVICE_NAME}/target/*.jar /app/app.jar
|
|
||||||
|
|
||||||
# 暴露端口
|
|
||||||
EXPOSE ${SERVICE_PORT}
|
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
|
|
||||||
CMD curl -f http://localhost:${SERVICE_PORT}/actuator/health || exit 1
|
|
||||||
|
|
||||||
# 启动应用
|
|
||||||
ENTRYPOINT ["/app/start.sh"]
|
|
||||||
84
docker/urbanLifeline/serv/build.sh
Normal file
84
docker/urbanLifeline/serv/build.sh
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - 后端服务镜像构建脚本
|
||||||
|
#
|
||||||
|
# 使用方式:
|
||||||
|
# ./build.sh # 构建 All-in-One 镜像 (推荐)
|
||||||
|
# ./build.sh base # 仅构建基础镜像
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 项目根目录 (相对于此脚本)
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# 镜像版本
|
||||||
|
VERSION=${IMAGE_VERSION:-latest}
|
||||||
|
|
||||||
|
# 服务列表
|
||||||
|
SERVICES=(gateway system auth file log message crontab bidding workcase platform ai)
|
||||||
|
|
||||||
|
# 构建基础镜像
|
||||||
|
build_base() {
|
||||||
|
echo "=========================================="
|
||||||
|
echo "构建基础镜像: urban-lifeline-base-serv:${VERSION}"
|
||||||
|
echo "=========================================="
|
||||||
|
docker build -t urban-lifeline-base-serv:${VERSION} \
|
||||||
|
-f docker/urbanLifeline/serv/Dockerfile.base .
|
||||||
|
|
||||||
|
if [ "$VERSION" != "latest" ]; then
|
||||||
|
docker tag urban-lifeline-base-serv:${VERSION} urban-lifeline-base-serv:latest
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 构建 All-in-One 镜像
|
||||||
|
build() {
|
||||||
|
echo "=========================================="
|
||||||
|
echo "构建 All-in-One 镜像: urban-lifeline-serv:${VERSION}"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# 先构建基础镜像
|
||||||
|
build_base
|
||||||
|
|
||||||
|
# 检查所有 JAR 文件
|
||||||
|
local missing=0
|
||||||
|
for service in "${SERVICES[@]}"; do
|
||||||
|
if ! ls urbanLifelineServ/${service}/target/*.jar 1> /dev/null 2>&1; then
|
||||||
|
echo "缺少: urbanLifelineServ/${service}/target/*.jar"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $missing -eq 1 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "请先执行 Maven 构建:"
|
||||||
|
echo " cd urbanLifelineServ && mvn clean package -DskipTests"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker build -t urban-lifeline-serv:${VERSION} \
|
||||||
|
-f docker/urbanLifeline/serv/Dockerfile.serv .
|
||||||
|
|
||||||
|
if [ "$VERSION" != "latest" ]; then
|
||||||
|
docker tag urban-lifeline-serv:${VERSION} urban-lifeline-serv:latest
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "镜像构建完成!"
|
||||||
|
echo ""
|
||||||
|
echo "管理服务:"
|
||||||
|
echo " docker exec urban-lifeline-serv /app/service-manager.sh status"
|
||||||
|
echo " docker exec urban-lifeline-serv /app/service-manager.sh restart gateway"
|
||||||
|
echo "=========================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主逻辑
|
||||||
|
case "${1:-build}" in
|
||||||
|
base)
|
||||||
|
build_base
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -1,180 +1,47 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
# Level 2: 后端微服务
|
# Urban Lifeline - All-in-One 部署
|
||||||
# gateway -> system -> file -> auth -> ai -> workcase
|
# 单容器运行所有后端服务
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# ====================== Gateway 网关服务 ======================
|
urban-lifeline-serv:
|
||||||
gateway:
|
image: urban-lifeline-serv:${IMAGE_VERSION:-latest}
|
||||||
image: urban-lifeline-gateway:${IMAGE_VERSION:-latest}
|
container_name: urban-lifeline-serv
|
||||||
container_name: urban-lifeline-gateway
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
networks:
|
||||||
- urban-lifeline
|
- urban-lifeline
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080" # gateway
|
||||||
|
- "8081:8081" # auth
|
||||||
|
- "8082:8082" # system
|
||||||
|
- "8083:8083" # log
|
||||||
|
- "8084:8084" # file
|
||||||
|
- "8085:8085" # message
|
||||||
|
- "8086:8086" # crontab
|
||||||
|
- "8087:8087" # bidding
|
||||||
|
- "8088:8088" # workcase
|
||||||
|
- "8089:8089" # platform
|
||||||
|
- "8090:8090" # ai
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
volumes:
|
||||||
- ${LOG_ROOT:-../volumes/logs}/gateway:/app/logs
|
- ${LOG_ROOT:-../../volumes/logs}:/app/logs
|
||||||
depends_on:
|
# 内存限制 (根据服务器配置调整)
|
||||||
nacos:
|
deploy:
|
||||||
condition: service_healthy
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
|
reservations:
|
||||||
|
memory: 2G
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 60s
|
start_period: 180s
|
||||||
|
|
||||||
# ====================== System 系统服务 ======================
|
|
||||||
system:
|
|
||||||
image: urban-lifeline-system:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-system
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "8082"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
|
||||||
- ${LOG_ROOT:-../volumes/logs}/system:/app/logs
|
|
||||||
depends_on:
|
|
||||||
gateway:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8082/actuator/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# ====================== File 文件服务 ======================
|
|
||||||
file:
|
|
||||||
image: urban-lifeline-file:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-file
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "8084"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
|
||||||
MINIO_ENDPOINT: ${MINIO_ENDPOINT:-http://minio:9000}
|
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
|
||||||
- ${LOG_ROOT:-../volumes/logs}/file:/app/logs
|
|
||||||
depends_on:
|
|
||||||
system:
|
|
||||||
condition: service_healthy
|
|
||||||
minio:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8084/actuator/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# ====================== Auth 认证服务 ======================
|
|
||||||
auth:
|
|
||||||
image: urban-lifeline-auth:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-auth
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "8081"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
|
||||||
- ${LOG_ROOT:-../volumes/logs}/auth:/app/logs
|
|
||||||
depends_on:
|
|
||||||
system:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8081/actuator/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# ====================== AI 智能服务 ======================
|
|
||||||
ai:
|
|
||||||
image: urban-lifeline-ai:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-ai
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "8090"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
|
||||||
DIFY_API_URL: ${DIFY_API_URL:-http://dify-api:5001}
|
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
|
||||||
- ${LOG_ROOT:-../volumes/logs}/ai:/app/logs
|
|
||||||
depends_on:
|
|
||||||
file:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8090/actuator/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# ====================== Workcase 工单服务 ======================
|
|
||||||
workcase:
|
|
||||||
image: urban-lifeline-workcase:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-workcase
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["serv", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "8088"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod}
|
|
||||||
NACOS_SERVER_ADDR: ${NACOS_SERVER_ADDR:-nacos:8848}
|
|
||||||
NACOS_NAMESPACE: ${NACOS_NAMESPACE:-}
|
|
||||||
JAVA_OPTS: "-Xms256m -Xmx512m"
|
|
||||||
volumes:
|
|
||||||
- ${LOG_ROOT:-../volumes/logs}/workcase:/app/logs
|
|
||||||
depends_on:
|
|
||||||
ai:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8088/actuator/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
urban-lifeline:
|
urban-lifeline:
|
||||||
|
|||||||
350
docker/urbanLifeline/serv/service-manager.sh
Normal file
350
docker/urbanLifeline/serv/service-manager.sh
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - 服务管理脚本
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./service-manager.sh start-all # 启动所有服务
|
||||||
|
# ./service-manager.sh start gateway # 启动单个服务
|
||||||
|
# ./service-manager.sh stop gateway # 停止单个服务
|
||||||
|
# ./service-manager.sh restart gateway # 重启单个服务
|
||||||
|
# ./service-manager.sh status # 查看所有服务状态
|
||||||
|
# ./service-manager.sh logs gateway # 查看服务日志
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 目录配置
|
||||||
|
JAR_DIR="/app/jars"
|
||||||
|
LOG_DIR="/app/logs"
|
||||||
|
PID_DIR="/app/pids"
|
||||||
|
|
||||||
|
# 服务配置: 服务名=端口:内存
|
||||||
|
declare -A SERVICES=(
|
||||||
|
["gateway"]="8080:384m"
|
||||||
|
["system"]="8082:384m"
|
||||||
|
["auth"]="8081:256m"
|
||||||
|
["file"]="8084:256m"
|
||||||
|
["log"]="8083:192m"
|
||||||
|
["message"]="8085:256m"
|
||||||
|
["crontab"]="8086:192m"
|
||||||
|
["ai"]="8090:384m"
|
||||||
|
["bidding"]="8087:256m"
|
||||||
|
["platform"]="8089:256m"
|
||||||
|
["workcase"]="8088:384m"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 启动顺序 (有依赖关系)
|
||||||
|
# BOOT_ORDER=(gateway system auth file log message crontab ai bidding platform workcase)
|
||||||
|
BOOT_ORDER=(gateway system auth file ai workcase)
|
||||||
|
|
||||||
|
# 颜色输出
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# 获取服务端口
|
||||||
|
get_port() {
|
||||||
|
local service=$1
|
||||||
|
echo "${SERVICES[$service]}" | cut -d: -f1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 获取服务内存配置
|
||||||
|
get_memory() {
|
||||||
|
local service=$1
|
||||||
|
echo "${SERVICES[$service]}" | cut -d: -f2
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查服务是否运行
|
||||||
|
is_running() {
|
||||||
|
local service=$1
|
||||||
|
local pid_file="${PID_DIR}/${service}.pid"
|
||||||
|
|
||||||
|
if [ -f "$pid_file" ]; then
|
||||||
|
local pid=$(cat "$pid_file")
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 等待服务就绪
|
||||||
|
wait_for_service() {
|
||||||
|
local service=$1
|
||||||
|
local port=$(get_port "$service")
|
||||||
|
local max_wait=60
|
||||||
|
local count=0
|
||||||
|
|
||||||
|
while [ $count -lt $max_wait ]; do
|
||||||
|
if curl -sf "http://localhost:${port}/actuator/health" > /dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
count=$((count + 2))
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 启动单个服务
|
||||||
|
start_service() {
|
||||||
|
local service=$1
|
||||||
|
local port=$(get_port "$service")
|
||||||
|
local memory=$(get_memory "$service")
|
||||||
|
local jar_file="${JAR_DIR}/${service}.jar"
|
||||||
|
local log_file="${LOG_DIR}/${service}.log"
|
||||||
|
local pid_file="${PID_DIR}/${service}.pid"
|
||||||
|
|
||||||
|
if [ ! -f "$jar_file" ]; then
|
||||||
|
log_error "JAR 文件不存在: $jar_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_running "$service"; then
|
||||||
|
log_warn "$service 已在运行 (PID: $(cat $pid_file))"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "启动 $service (端口: $port, 内存: $memory)..."
|
||||||
|
|
||||||
|
# JVM 参数
|
||||||
|
local java_opts="-Xms128m -Xmx${memory} -XX:+UseG1GC -XX:MaxGCPauseMillis=100"
|
||||||
|
java_opts="$java_opts -Djava.security.egd=file:/dev/./urandom"
|
||||||
|
java_opts="$java_opts -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod}"
|
||||||
|
|
||||||
|
# Nacos 配置
|
||||||
|
if [ -n "$NACOS_SERVER_ADDR" ]; then
|
||||||
|
java_opts="$java_opts -Dspring.cloud.nacos.discovery.server-addr=$NACOS_SERVER_ADDR"
|
||||||
|
java_opts="$java_opts -Dspring.cloud.nacos.config.server-addr=$NACOS_SERVER_ADDR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$NACOS_NAMESPACE" ]; then
|
||||||
|
java_opts="$java_opts -Dspring.cloud.nacos.discovery.namespace=$NACOS_NAMESPACE"
|
||||||
|
java_opts="$java_opts -Dspring.cloud.nacos.config.namespace=$NACOS_NAMESPACE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
nohup java $java_opts -jar "$jar_file" > "$log_file" 2>&1 &
|
||||||
|
local pid=$!
|
||||||
|
echo $pid > "$pid_file"
|
||||||
|
|
||||||
|
log_info "$service 已启动 (PID: $pid)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 停止单个服务
|
||||||
|
stop_service() {
|
||||||
|
local service=$1
|
||||||
|
local pid_file="${PID_DIR}/${service}.pid"
|
||||||
|
|
||||||
|
if ! is_running "$service"; then
|
||||||
|
log_warn "$service 未在运行"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pid=$(cat "$pid_file")
|
||||||
|
log_info "停止 $service (PID: $pid)..."
|
||||||
|
|
||||||
|
# 优雅关闭
|
||||||
|
kill -15 "$pid" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 等待进程退出
|
||||||
|
local count=0
|
||||||
|
while [ $count -lt 30 ] && kill -0 "$pid" 2>/dev/null; do
|
||||||
|
sleep 1
|
||||||
|
count=$((count + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# 强制关闭
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
log_warn "强制终止 $service..."
|
||||||
|
kill -9 "$pid" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$pid_file"
|
||||||
|
log_info "$service 已停止"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 重启单个服务
|
||||||
|
restart_service() {
|
||||||
|
local service=$1
|
||||||
|
stop_service "$service"
|
||||||
|
sleep 2
|
||||||
|
start_service "$service"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 启动所有服务
|
||||||
|
start_all() {
|
||||||
|
log_info "=========================================="
|
||||||
|
log_info " Urban Lifeline - 启动所有服务"
|
||||||
|
log_info "=========================================="
|
||||||
|
|
||||||
|
# 等待 Nacos
|
||||||
|
if [ -n "$NACOS_SERVER_ADDR" ]; then
|
||||||
|
log_info "等待 Nacos 就绪..."
|
||||||
|
local nacos_host=$(echo $NACOS_SERVER_ADDR | cut -d: -f1)
|
||||||
|
local nacos_port=$(echo $NACOS_SERVER_ADDR | cut -d: -f2)
|
||||||
|
|
||||||
|
for i in $(seq 1 30); do
|
||||||
|
if curl -sf "http://${nacos_host}:${nacos_port}/nacos/" > /dev/null 2>&1; then
|
||||||
|
log_info "Nacos 已就绪"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 按顺序启动服务,等待健康检查通过后再启动下一个
|
||||||
|
for service in "${BOOT_ORDER[@]}"; do
|
||||||
|
start_service "$service"
|
||||||
|
|
||||||
|
log_info "等待 $service 健康检查..."
|
||||||
|
if wait_for_service "$service"; then
|
||||||
|
log_info "$service 已就绪 ✓"
|
||||||
|
else
|
||||||
|
log_warn "$service 健康检查超时,继续启动下一个服务"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "=========================================="
|
||||||
|
log_info " 所有服务启动完成"
|
||||||
|
log_info "=========================================="
|
||||||
|
|
||||||
|
show_status
|
||||||
|
|
||||||
|
# 保持容器运行并监控
|
||||||
|
monitor_services
|
||||||
|
}
|
||||||
|
|
||||||
|
# 停止所有服务
|
||||||
|
stop_all() {
|
||||||
|
log_info "停止所有服务..."
|
||||||
|
|
||||||
|
# 逆序停止
|
||||||
|
for ((i=${#BOOT_ORDER[@]}-1; i>=0; i--)); do
|
||||||
|
stop_service "${BOOT_ORDER[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "所有服务已停止"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查看服务状态
|
||||||
|
show_status() {
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Urban Lifeline 服务状态"
|
||||||
|
echo "=========================================="
|
||||||
|
printf "%-12s %-8s %-8s %-10s\n" "服务" "端口" "PID" "状态"
|
||||||
|
echo "------------------------------------------"
|
||||||
|
|
||||||
|
for service in "${BOOT_ORDER[@]}"; do
|
||||||
|
local port=$(get_port "$service")
|
||||||
|
local pid_file="${PID_DIR}/${service}.pid"
|
||||||
|
local pid="-"
|
||||||
|
local status="${RED}停止${NC}"
|
||||||
|
|
||||||
|
if [ -f "$pid_file" ]; then
|
||||||
|
pid=$(cat "$pid_file")
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
status="${GREEN}运行中${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-12s %-8s %-8s " "$service" "$port" "$pid"
|
||||||
|
echo -e "$status"
|
||||||
|
done
|
||||||
|
echo "=========================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查看服务日志
|
||||||
|
show_logs() {
|
||||||
|
local service=$1
|
||||||
|
local log_file="${LOG_DIR}/${service}.log"
|
||||||
|
|
||||||
|
if [ ! -f "$log_file" ]; then
|
||||||
|
log_error "日志文件不存在: $log_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tail -f "$log_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 监控服务 (保持容器运行)
|
||||||
|
monitor_services() {
|
||||||
|
log_info "进入监控模式..."
|
||||||
|
|
||||||
|
# 捕获退出信号
|
||||||
|
trap 'stop_all; exit 0' SIGTERM SIGINT
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
sleep 30
|
||||||
|
|
||||||
|
# 检查服务状态,自动重启挂掉的服务
|
||||||
|
for service in "${BOOT_ORDER[@]}"; do
|
||||||
|
if ! is_running "$service"; then
|
||||||
|
log_warn "$service 已停止,尝试重启..."
|
||||||
|
start_service "$service"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主入口
|
||||||
|
case "${1:-help}" in
|
||||||
|
start-all)
|
||||||
|
start_all
|
||||||
|
;;
|
||||||
|
stop-all)
|
||||||
|
stop_all
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
log_error "请指定服务名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
start_service "$2"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
log_error "请指定服务名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
stop_service "$2"
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
log_error "请指定服务名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
restart_service "$2"
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
log_error "请指定服务名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
show_logs "$2"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Urban Lifeline 服务管理"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 <命令> [服务名]"
|
||||||
|
echo ""
|
||||||
|
echo "命令:"
|
||||||
|
echo " start-all 启动所有服务"
|
||||||
|
echo " stop-all 停止所有服务"
|
||||||
|
echo " start <服务> 启动指定服务"
|
||||||
|
echo " stop <服务> 停止指定服务"
|
||||||
|
echo " restart <服务> 重启指定服务"
|
||||||
|
echo " status 查看服务状态"
|
||||||
|
echo " logs <服务> 查看服务日志"
|
||||||
|
echo ""
|
||||||
|
echo "可用服务: ${!SERVICES[*]}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# ================================================
|
|
||||||
# Urban Lifeline - 前端 Dockerfile 模板
|
|
||||||
# 基于 Nginx Alpine,提供静态文件服务
|
|
||||||
#
|
|
||||||
# 构建参数:
|
|
||||||
# WEB_NAME - 前端项目名称 (platform/workcase)
|
|
||||||
#
|
|
||||||
# 构建命令示例:
|
|
||||||
# docker build -t urban-lifeline-platform:latest \
|
|
||||||
# --build-arg WEB_NAME=platform \
|
|
||||||
# -f docker/urbanLifeline/web/Dockerfile .
|
|
||||||
# ================================================
|
|
||||||
FROM nginx:alpine
|
|
||||||
|
|
||||||
ARG WEB_NAME
|
|
||||||
|
|
||||||
ENV TZ=Asia/Shanghai
|
|
||||||
|
|
||||||
# 安装基础工具
|
|
||||||
RUN apk add --no-cache tzdata curl \
|
|
||||||
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
|
||||||
&& echo "Asia/Shanghai" > /etc/timezone
|
|
||||||
|
|
||||||
# 复制 Nginx 配置
|
|
||||||
COPY docker/urbanLifeline/web/nginx.conf /etc/nginx/nginx.conf
|
|
||||||
|
|
||||||
# 复制前端构建产物
|
|
||||||
COPY urbanLifelineWeb/packages/${WEB_NAME}/dist/ /usr/share/nginx/html/
|
|
||||||
|
|
||||||
# 暴露端口
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
# 健康检查
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
|
|
||||||
CMD curl -f http://localhost/ || exit 1
|
|
||||||
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
46
docker/urbanLifeline/web/Dockerfile.web
Normal file
46
docker/urbanLifeline/web/Dockerfile.web
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - All-in-One 前端镜像
|
||||||
|
# 使用 Node.js 静态服务器,端口可配置
|
||||||
|
#
|
||||||
|
# 构建: docker build -t urban-lifeline-web:latest -f Dockerfile.web .
|
||||||
|
# ================================================
|
||||||
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
RUN apk add --no-cache tzdata curl bash \
|
||||||
|
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
|
&& echo "Asia/Shanghai" > /etc/timezone
|
||||||
|
|
||||||
|
# 安装静态文件服务器
|
||||||
|
RUN npm install -g serve
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制管理脚本
|
||||||
|
COPY docker/urbanLifeline/web/web-manager.sh /app/web-manager.sh
|
||||||
|
RUN chmod +x /app/web-manager.sh
|
||||||
|
|
||||||
|
# 复制 shared 公共模块 (Module Federation 远程模块,必须最先启动)
|
||||||
|
COPY urbanLifelineWeb/packages/shared/dist/ /app/sites/shared/
|
||||||
|
|
||||||
|
# 复制所有前端构建产物
|
||||||
|
COPY urbanLifelineWeb/packages/platform/dist/ /app/sites/platform/
|
||||||
|
COPY urbanLifelineWeb/packages/workcase/dist/ /app/sites/workcase/
|
||||||
|
COPY urbanLifelineWeb/packages/bidding/dist/ /app/sites/bidding/
|
||||||
|
COPY urbanLifelineWeb/packages/workcase_wechat/dist/ /app/sites/workcase_wechat/
|
||||||
|
|
||||||
|
# 默认端口 (可通过环境变量覆盖)
|
||||||
|
ENV SHARED_PORT=8000 \
|
||||||
|
PLATFORM_PORT=8001 \
|
||||||
|
WORKCASE_PORT=8002 \
|
||||||
|
BIDDING_PORT=8003 \
|
||||||
|
WORKCASE_WECHAT_PORT=8004
|
||||||
|
|
||||||
|
EXPOSE 8000 8001 8002 8003 8004
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:${SHARED_PORT}/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/web-manager.sh"]
|
||||||
|
CMD ["start-all"]
|
||||||
59
docker/urbanLifeline/web/build.sh
Normal file
59
docker/urbanLifeline/web/build.sh
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - 前端镜像构建脚本
|
||||||
|
#
|
||||||
|
# 使用方式:
|
||||||
|
# ./build.sh # 构建 All-in-One 镜像
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 项目根目录 (相对于此脚本)
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# 镜像版本
|
||||||
|
VERSION=${IMAGE_VERSION:-latest}
|
||||||
|
|
||||||
|
# 前端站点列表
|
||||||
|
SITES=(shared platform workcase bidding workcase_wechat)
|
||||||
|
|
||||||
|
# 构建 All-in-One 镜像
|
||||||
|
build() {
|
||||||
|
echo "=========================================="
|
||||||
|
echo "构建 All-in-One 前端镜像: urban-lifeline-web:${VERSION}"
|
||||||
|
echo "=========================================="
|
||||||
|
|
||||||
|
# 检查所有 dist 目录
|
||||||
|
local missing=0
|
||||||
|
for site in "${SITES[@]}"; do
|
||||||
|
if [ ! -d "urbanLifelineWeb/packages/${site}/dist" ]; then
|
||||||
|
echo "缺少: urbanLifelineWeb/packages/${site}/dist"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $missing -eq 1 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "请先执行前端构建:"
|
||||||
|
echo " cd urbanLifelineWeb && pnpm build"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker build -t urban-lifeline-web:${VERSION} \
|
||||||
|
-f docker/urbanLifeline/web/Dockerfile.web .
|
||||||
|
|
||||||
|
if [ "$VERSION" != "latest" ]; then
|
||||||
|
docker tag urban-lifeline-web:${VERSION} urban-lifeline-web:latest
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo "镜像构建完成!"
|
||||||
|
echo ""
|
||||||
|
echo "管理服务:"
|
||||||
|
echo " docker exec urban-lifeline-web /app/web-manager.sh status"
|
||||||
|
echo " docker exec urban-lifeline-web /app/web-manager.sh restart platform"
|
||||||
|
echo "=========================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
build
|
||||||
@@ -1,47 +1,40 @@
|
|||||||
# ================================================
|
# ================================================
|
||||||
# Level 3: 前端应用
|
# Urban Lifeline - All-in-One 前端部署
|
||||||
# 每个前端独立 Nginx 容器
|
# 单容器运行所有前端应用
|
||||||
# platform (8001) / workcase (8002)
|
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# ====================== Platform 管理平台 ======================
|
urban-lifeline-web:
|
||||||
platform:
|
image: urban-lifeline-web:${IMAGE_VERSION:-latest}
|
||||||
image: urban-lifeline-platform:${IMAGE_VERSION:-latest}
|
container_name: urban-lifeline-web
|
||||||
container_name: urban-lifeline-platform
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
profiles: ["web", "all"]
|
|
||||||
networks:
|
networks:
|
||||||
- urban-lifeline
|
- urban-lifeline
|
||||||
expose:
|
ports:
|
||||||
- "80"
|
- "${PLATFORM_PORT:-8001}:${PLATFORM_PORT:-8001}"
|
||||||
|
- "${WORKCASE_PORT:-8002}:${WORKCASE_PORT:-8002}"
|
||||||
|
- "${BIDDING_PORT:-8003}:${BIDDING_PORT:-8003}"
|
||||||
|
- "${WORKCASE_WECHAT_PORT:-8004}:${WORKCASE_WECHAT_PORT:-8004}"
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
|
PLATFORM_PORT: ${PLATFORM_PORT:-8001}
|
||||||
|
WORKCASE_PORT: ${WORKCASE_PORT:-8002}
|
||||||
|
BIDDING_PORT: ${BIDDING_PORT:-8003}
|
||||||
|
WORKCASE_WECHAT_PORT: ${WORKCASE_WECHAT_PORT:-8004}
|
||||||
|
volumes:
|
||||||
|
- ${LOG_ROOT:-../../volumes/logs}/web:/app/logs
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 512M
|
||||||
|
reservations:
|
||||||
|
memory: 128M
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
test: ["CMD", "curl", "-f", "http://localhost:${PLATFORM_PORT:-8001}/"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
start_period: 10s
|
start_period: 30s
|
||||||
|
|
||||||
# ====================== Workcase 工单系统 ======================
|
|
||||||
workcase-web:
|
|
||||||
image: urban-lifeline-workcase-web:${IMAGE_VERSION:-latest}
|
|
||||||
container_name: urban-lifeline-workcase-web
|
|
||||||
restart: unless-stopped
|
|
||||||
profiles: ["web", "all"]
|
|
||||||
networks:
|
|
||||||
- urban-lifeline
|
|
||||||
expose:
|
|
||||||
- "80"
|
|
||||||
environment:
|
|
||||||
TZ: Asia/Shanghai
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 10s
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
urban-lifeline:
|
urban-lifeline:
|
||||||
|
|||||||
270
docker/urbanLifeline/web/web-manager.sh
Normal file
270
docker/urbanLifeline/web/web-manager.sh
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ================================================
|
||||||
|
# Urban Lifeline - 前端服务管理脚本
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./web-manager.sh start-all # 启动所有前端
|
||||||
|
# ./web-manager.sh start platform # 启动单个前端
|
||||||
|
# ./web-manager.sh stop platform # 停止单个前端
|
||||||
|
# ./web-manager.sh restart platform # 重启单个前端
|
||||||
|
# ./web-manager.sh status # 查看状态
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SITES_DIR="/app/sites"
|
||||||
|
PID_DIR="/app/pids"
|
||||||
|
LOG_DIR="/app/logs"
|
||||||
|
|
||||||
|
mkdir -p "$PID_DIR" "$LOG_DIR"
|
||||||
|
|
||||||
|
# 前端配置: 名称=端口环境变量名:默认端口
|
||||||
|
declare -A WEBS=(
|
||||||
|
["shared"]="SHARED_PORT:8000"
|
||||||
|
["platform"]="PLATFORM_PORT:8001"
|
||||||
|
["workcase"]="WORKCASE_PORT:8002"
|
||||||
|
["bidding"]="BIDDING_PORT:8003"
|
||||||
|
["workcase_wechat"]="WORKCASE_WECHAT_PORT:8004"
|
||||||
|
)
|
||||||
|
|
||||||
|
# shared 必须最先启动 (其他模块依赖它)
|
||||||
|
BOOT_ORDER=(shared platform workcase bidding workcase_wechat)
|
||||||
|
|
||||||
|
# 颜色
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# 获取端口
|
||||||
|
get_port() {
|
||||||
|
local web=$1
|
||||||
|
local config=${WEBS[$web]}
|
||||||
|
local env_name=$(echo "$config" | cut -d: -f1)
|
||||||
|
local default_port=$(echo "$config" | cut -d: -f2)
|
||||||
|
echo "${!env_name:-$default_port}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查是否运行
|
||||||
|
is_running() {
|
||||||
|
local web=$1
|
||||||
|
local pid_file="${PID_DIR}/${web}.pid"
|
||||||
|
|
||||||
|
if [ -f "$pid_file" ]; then
|
||||||
|
local pid=$(cat "$pid_file")
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 等待服务就绪
|
||||||
|
wait_for_web() {
|
||||||
|
local web=$1
|
||||||
|
local port=$(get_port "$web")
|
||||||
|
local max_wait=30
|
||||||
|
local count=0
|
||||||
|
|
||||||
|
while [ $count -lt $max_wait ]; do
|
||||||
|
if curl -sf "http://localhost:${port}/" > /dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
count=$((count + 1))
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 启动单个前端
|
||||||
|
start_web() {
|
||||||
|
local web=$1
|
||||||
|
local port=$(get_port "$web")
|
||||||
|
local site_dir="${SITES_DIR}/${web}"
|
||||||
|
local pid_file="${PID_DIR}/${web}.pid"
|
||||||
|
local log_file="${LOG_DIR}/${web}.log"
|
||||||
|
|
||||||
|
if [ ! -d "$site_dir" ]; then
|
||||||
|
log_error "站点目录不存在: $site_dir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_running "$web"; then
|
||||||
|
log_warn "$web 已在运行 (PID: $(cat $pid_file))"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "启动 $web (端口: $port)..."
|
||||||
|
|
||||||
|
# 使用 serve 启动静态服务
|
||||||
|
nohup serve -s "$site_dir" -l "$port" > "$log_file" 2>&1 &
|
||||||
|
local pid=$!
|
||||||
|
echo $pid > "$pid_file"
|
||||||
|
|
||||||
|
log_info "$web 已启动 (PID: $pid)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 停止单个前端
|
||||||
|
stop_web() {
|
||||||
|
local web=$1
|
||||||
|
local pid_file="${PID_DIR}/${web}.pid"
|
||||||
|
|
||||||
|
if ! is_running "$web"; then
|
||||||
|
log_warn "$web 未在运行"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pid=$(cat "$pid_file")
|
||||||
|
log_info "停止 $web (PID: $pid)..."
|
||||||
|
|
||||||
|
kill -15 "$pid" 2>/dev/null || true
|
||||||
|
|
||||||
|
local count=0
|
||||||
|
while [ $count -lt 10 ] && kill -0 "$pid" 2>/dev/null; do
|
||||||
|
sleep 1
|
||||||
|
count=$((count + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
kill -9 "$pid" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$pid_file"
|
||||||
|
log_info "$web 已停止"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 重启
|
||||||
|
restart_web() {
|
||||||
|
local web=$1
|
||||||
|
stop_web "$web"
|
||||||
|
sleep 1
|
||||||
|
start_web "$web"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 启动所有
|
||||||
|
start_all() {
|
||||||
|
log_info "=========================================="
|
||||||
|
log_info " Urban Lifeline - 启动所有前端"
|
||||||
|
log_info "=========================================="
|
||||||
|
|
||||||
|
for web in "${BOOT_ORDER[@]}"; do
|
||||||
|
start_web "$web"
|
||||||
|
|
||||||
|
log_info "等待 $web 就绪..."
|
||||||
|
if wait_for_web "$web"; then
|
||||||
|
log_info "$web 已就绪 ✓"
|
||||||
|
else
|
||||||
|
log_warn "$web 健康检查超时"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "=========================================="
|
||||||
|
log_info " 所有前端启动完成"
|
||||||
|
log_info "=========================================="
|
||||||
|
|
||||||
|
show_status
|
||||||
|
monitor_webs
|
||||||
|
}
|
||||||
|
|
||||||
|
# 停止所有
|
||||||
|
stop_all() {
|
||||||
|
log_info "停止所有前端..."
|
||||||
|
for web in "${BOOT_ORDER[@]}"; do
|
||||||
|
stop_web "$web"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 状态
|
||||||
|
show_status() {
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Urban Lifeline 前端状态"
|
||||||
|
echo "=========================================="
|
||||||
|
printf "%-18s %-8s %-8s %-10s\n" "站点" "端口" "PID" "状态"
|
||||||
|
echo "------------------------------------------"
|
||||||
|
|
||||||
|
for web in "${BOOT_ORDER[@]}"; do
|
||||||
|
local port=$(get_port "$web")
|
||||||
|
local pid_file="${PID_DIR}/${web}.pid"
|
||||||
|
local pid="-"
|
||||||
|
local status="${RED}停止${NC}"
|
||||||
|
|
||||||
|
if [ -f "$pid_file" ]; then
|
||||||
|
pid=$(cat "$pid_file")
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
status="${GREEN}运行中${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-18s %-8s %-8s " "$web" "$port" "$pid"
|
||||||
|
echo -e "$status"
|
||||||
|
done
|
||||||
|
echo "=========================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
# 监控
|
||||||
|
monitor_webs() {
|
||||||
|
log_info "进入监控模式..."
|
||||||
|
trap 'stop_all; exit 0' SIGTERM SIGINT
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
sleep 30
|
||||||
|
for web in "${BOOT_ORDER[@]}"; do
|
||||||
|
if ! is_running "$web"; then
|
||||||
|
log_warn "$web 已停止,尝试重启..."
|
||||||
|
start_web "$web"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主入口
|
||||||
|
case "${1:-help}" in
|
||||||
|
start-all)
|
||||||
|
start_all
|
||||||
|
;;
|
||||||
|
stop-all)
|
||||||
|
stop_all
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
[ -z "$2" ] && { log_error "请指定站点名"; exit 1; }
|
||||||
|
start_web "$2"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
[ -z "$2" ] && { log_error "请指定站点名"; exit 1; }
|
||||||
|
stop_web "$2"
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
[ -z "$2" ] && { log_error "请指定站点名"; exit 1; }
|
||||||
|
restart_web "$2"
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Urban Lifeline 前端管理"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 <命令> [站点名]"
|
||||||
|
echo ""
|
||||||
|
echo "命令:"
|
||||||
|
echo " start-all 启动所有前端"
|
||||||
|
echo " stop-all 停止所有前端"
|
||||||
|
echo " start <站点> 启动指定站点"
|
||||||
|
echo " stop <站点> 停止指定站点"
|
||||||
|
echo " restart <站点> 重启指定站点"
|
||||||
|
echo " status 查看状态"
|
||||||
|
echo ""
|
||||||
|
echo "可用站点: ${!WEBS[*]}"
|
||||||
|
echo ""
|
||||||
|
echo "端口配置 (环境变量):"
|
||||||
|
echo " SHARED_PORT 默认 8000 (公共模块,必须最先启动)"
|
||||||
|
echo " PLATFORM_PORT 默认 8001"
|
||||||
|
echo " WORKCASE_PORT 默认 8002"
|
||||||
|
echo " BIDDING_PORT 默认 8003"
|
||||||
|
echo " WORKCASE_WECHAT_PORT 默认 8004"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user