修改
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 serv up -d
|
||||
# 启动前端服务: docker compose --profile web up -d
|
||||
# 停止所有服务: docker compose down
|
||||
# 查看日志: docker compose logs -f [service_name]
|
||||
#
|
||||
# All-in-One 模式:
|
||||
# - urban-lifeline-serv: 所有后端服务 (单容器)
|
||||
# - urban-lifeline-web: 所有前端应用 (单容器)
|
||||
# - nginx: 反向代理
|
||||
# ================================================
|
||||
|
||||
name: urban-lifeline
|
||||
|
||||
# 引入子目录的 compose 文件
|
||||
include:
|
||||
# Level 1: 基础设施
|
||||
# 基础设施 + 业务服务 (All-in-One)
|
||||
- path: ./infra/docker-compose.yml
|
||||
# Level 2: 后端服务
|
||||
- path: ./urbanLifeline/serv/docker-compose.yml
|
||||
# Level 3: 前端服务
|
||||
- path: ./urbanLifeline/web/docker-compose.yml
|
||||
|
||||
# 共享网络定义
|
||||
networks:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
services:
|
||||
# ====================== Nginx 反向代理 ======================
|
||||
nginx:
|
||||
image: urban-lifeline-web:${IMAGE_VERSION:-latest}
|
||||
image: nginx:alpine
|
||||
container_name: urban-lifeline-nginx
|
||||
restart: unless-stopped
|
||||
profiles: ["infra", "all"]
|
||||
@@ -23,6 +23,9 @@ services:
|
||||
- ./nginx/conf.d:/etc/nginx/conf.d:ro
|
||||
# SSL 证书(可选)
|
||||
# - ./nginx/ssl:/etc/nginx/ssl:ro
|
||||
depends_on:
|
||||
- urban-lifeline-serv
|
||||
- urban-lifeline-web
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/health"]
|
||||
interval: 30s
|
||||
@@ -30,6 +33,73 @@ services:
|
||||
retries: 3
|
||||
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:
|
||||
image: nacos/nacos-server:v3.1.0
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
# ================================================
|
||||
# Urban Lifeline - 站点配置
|
||||
# Urban Lifeline - 站点配置 (All-in-One 模式)
|
||||
# ================================================
|
||||
|
||||
# 上游服务定义
|
||||
# 上游服务定义 - 后端 All-in-One 容器
|
||||
upstream gateway {
|
||||
server gateway:8080;
|
||||
server urban-lifeline-serv:8080;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
# 上游服务定义 - 前端 All-in-One 容器
|
||||
upstream shared {
|
||||
server urban-lifeline-web:8000;
|
||||
}
|
||||
|
||||
upstream platform {
|
||||
server platform:80;
|
||||
server urban-lifeline-web:8001;
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -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 管理平台
|
||||
location /platform/ {
|
||||
proxy_pass http://platform/;
|
||||
@@ -39,7 +67,7 @@ server {
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
# Workcase 工单系统
|
||||
# Workcase 工单系统 PC端
|
||||
location /workcase/ {
|
||||
proxy_pass http://workcase-web/;
|
||||
proxy_http_version 1.1;
|
||||
@@ -49,6 +77,26 @@ server {
|
||||
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)
|
||||
location = / {
|
||||
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: 后端微服务
|
||||
# gateway -> system -> file -> auth -> ai -> workcase
|
||||
# Urban Lifeline - All-in-One 部署
|
||||
# 单容器运行所有后端服务
|
||||
# ================================================
|
||||
|
||||
services:
|
||||
# ====================== Gateway 网关服务 ======================
|
||||
gateway:
|
||||
image: urban-lifeline-gateway:${IMAGE_VERSION:-latest}
|
||||
container_name: urban-lifeline-gateway
|
||||
urban-lifeline-serv:
|
||||
image: urban-lifeline-serv:${IMAGE_VERSION:-latest}
|
||||
container_name: urban-lifeline-serv
|
||||
restart: unless-stopped
|
||||
profiles: ["serv", "all"]
|
||||
networks:
|
||||
- urban-lifeline
|
||||
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:
|
||||
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}/gateway:/app/logs
|
||||
depends_on:
|
||||
nacos:
|
||||
condition: service_healthy
|
||||
- ${LOG_ROOT:-../../volumes/logs}:/app/logs
|
||||
# 内存限制 (根据服务器配置调整)
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 4G
|
||||
reservations:
|
||||
memory: 2G
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
# ====================== 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
|
||||
start_period: 180s
|
||||
|
||||
networks:
|
||||
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: 前端应用
|
||||
# 每个前端独立 Nginx 容器
|
||||
# platform (8001) / workcase (8002)
|
||||
# Urban Lifeline - All-in-One 前端部署
|
||||
# 单容器运行所有前端应用
|
||||
# ================================================
|
||||
|
||||
services:
|
||||
# ====================== Platform 管理平台 ======================
|
||||
platform:
|
||||
image: urban-lifeline-platform:${IMAGE_VERSION:-latest}
|
||||
container_name: urban-lifeline-platform
|
||||
urban-lifeline-web:
|
||||
image: urban-lifeline-web:${IMAGE_VERSION:-latest}
|
||||
container_name: urban-lifeline-web
|
||||
restart: unless-stopped
|
||||
profiles: ["web", "all"]
|
||||
networks:
|
||||
- urban-lifeline
|
||||
expose:
|
||||
- "80"
|
||||
ports:
|
||||
- "${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:
|
||||
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:
|
||||
test: ["CMD", "curl", "-f", "http://localhost/"]
|
||||
test: ["CMD", "curl", "-f", "http://localhost:${PLATFORM_PORT:-8001}/"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# ====================== 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
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
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