compliance/create-compose-package.sh
2025-08-18 16:27:39 +08:00

442 lines
13 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# DMS合规性测试工具 - Docker Compose版本部署包创建脚本
# 使用Alpine Linux + 多阶段构建 + Docker Compose管理
# 支持多架构构建 (amd64 + arm64)
set -e
# 配置变量
EXPORT_DIR="dms-compliance-compose-$(date +%Y%m%d-%H%M%S)"
IMAGE_NAME="compliance-dms-mini"
ARCHIVE_NAME="$EXPORT_DIR.tar.gz"
TARGET_PLATFORMS="linux/amd64,linux/arm64"
echo "=== DMS合规性测试工具 Docker Compose版本部署包创建脚本 ==="
echo "[信息] 使用Docker Compose管理完全兼容原版架构"
echo "[信息] 目标架构: $TARGET_PLATFORMS"
# 检查Docker是否运行
if ! docker info >/dev/null 2>&1; then
echo "[错误] Docker未运行或无法访问"
exit 1
fi
# 检查是否支持buildx用于跨平台构建
if ! docker buildx version >/dev/null 2>&1; then
echo "[警告] Docker buildx不可用将使用传统构建方式"
USE_BUILDX=false
TARGET_PLATFORMS="linux/amd64" # 降级到单架构
else
echo "[信息] 检测到Docker buildx支持多架构构建"
USE_BUILDX=true
# 让用户选择构建架构
echo ""
echo "请选择构建架构:"
echo "1) 仅 AMD64 (x86_64) - 适用于大多数服务器"
echo "2) 仅 ARM64 (aarch64) - 适用于Apple Silicon Mac、ARM服务器"
echo "3) 多架构 (AMD64 + ARM64) - 通用兼容,但构建时间较长"
echo ""
read -p "请输入选择 (1-3默认3): " -r ARCH_CHOICE
case "${ARCH_CHOICE:-3}" in
1)
TARGET_PLATFORMS="linux/amd64"
echo "[信息] 选择构建架构: AMD64 only"
;;
2)
TARGET_PLATFORMS="linux/arm64"
echo "[信息] 选择构建架构: ARM64 only"
;;
3|*)
TARGET_PLATFORMS="linux/amd64,linux/arm64"
echo "[信息] 选择构建架构: 多架构 (AMD64 + ARM64)"
;;
esac
fi
echo "[信息] 最终目标架构: $TARGET_PLATFORMS"
# 创建导出目录
echo "[信息] 创建导出目录: $EXPORT_DIR"
rm -rf "$EXPORT_DIR"
mkdir -p "$EXPORT_DIR"
# 1. 创建临时构建目录,只包含必要文件
echo "[信息] 创建临时构建目录..."
TEMP_BUILD_DIR=$(mktemp -d)
trap "rm -rf $TEMP_BUILD_DIR" EXIT
# 白名单:只复制必要的文件
echo "[信息] 复制必要文件(超精简模式)..."
mkdir -p "$TEMP_BUILD_DIR"/{ddms_compliance_suite,custom_stages,custom_testcases,templates,static,assets}
# 只复制核心Python文件
echo "[信息] 复制核心Python文件..."
for file in api_server.py history_viewer.py flask_app.py; do
[ -f "$file" ] && cp "$file" "$TEMP_BUILD_DIR/"
done
# 复制核心目录(排除缓存和临时文件)
echo "[信息] 复制核心目录..."
rsync -av --exclude='__pycache__' --exclude='*.pyc' --exclude='*.log' ddms_compliance_suite/ "$TEMP_BUILD_DIR/ddms_compliance_suite/"
rsync -av --exclude='__pycache__' --exclude='*.pyc' custom_stages/ "$TEMP_BUILD_DIR/custom_stages/"
rsync -av --exclude='__pycache__' --exclude='*.pyc' custom_testcases/ "$TEMP_BUILD_DIR/custom_testcases/"
# 确保templates目录结构正确
echo "[信息] 复制模板和静态文件..."
rsync -av templates/ "$TEMP_BUILD_DIR/templates/"
rsync -av static/ "$TEMP_BUILD_DIR/static/"
rsync -av assets/ "$TEMP_BUILD_DIR/assets/"
# 验证templates目录内容
echo "[信息] 验证templates目录: $(ls "$TEMP_BUILD_DIR/templates/" 2>/dev/null | wc -l) 个文件"
echo "[信息] templates文件列表: $(ls "$TEMP_BUILD_DIR/templates/" 2>/dev/null | tr '\n' ' ')"
# 复制完整的requirements.txt
echo "[信息] 复制完整的requirements.txt..."
cp requirements.txt "$TEMP_BUILD_DIR/"
# 创建超轻量级Dockerfile
echo "[信息] 创建超轻量级Dockerfile..."
cat > "$TEMP_BUILD_DIR/Dockerfile" << 'EOF'
# 多阶段构建:第一阶段安装依赖
FROM python:3.9-alpine AS builder
# 安装构建依赖
RUN apk add --no-cache gcc musl-dev linux-headers
# 设置工作目录
WORKDIR /app
# 复制requirements并安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# 第二阶段:运行时镜像
FROM python:3.9-alpine
# 安装运行时依赖
RUN apk add --no-cache supervisor curl && \
rm -rf /var/cache/apk/*
# 从构建阶段复制Python包
COPY --from=builder /root/.local /root/.local
# 设置工作目录
WORKDIR /app
# 复制应用代码
COPY . .
# 创建supervisor配置
RUN mkdir -p /etc/supervisor/conf.d
COPY supervisord.conf /etc/supervisor/conf.d/
# 创建日志目录
RUN mkdir -p /var/log/supervisor /app/logs /app/test_reports /app/uploads
# 设置环境变量
ENV PATH=/root/.local/bin:$PATH
ENV PYTHONPATH=/app
ENV FLASK_ENV=production
ENV PYTHONUNBUFFERED=1
# 暴露端口(两个服务的端口)
EXPOSE 5050 5051
# 启动supervisor
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
EOF
# 创建supervisor配置
echo "[信息] 创建supervisor配置..."
cat > "$TEMP_BUILD_DIR/supervisord.conf" << 'EOF'
[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisor
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
[unix_http_server]
file=/tmp/supervisor.sock
chmod=0700
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
# DMS API服务器 (主服务)
[program:api_server]
command=python api_server.py
directory=/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/supervisor/api_server.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
environment=PYTHONPATH="/app",PYTHONUNBUFFERED="1"
# 历史查看器服务
[program:history_viewer]
command=python history_viewer.py
directory=/app
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/log/supervisor/history_viewer.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
environment=PYTHONPATH="/app",PYTHONUNBUFFERED="1"
# 进程组配置
[group:dms_services]
programs=api_server,history_viewer
priority=999
EOF
# 显示构建目录大小
echo "[信息] 临时构建目录大小: $(du -sh "$TEMP_BUILD_DIR" | cut -f1)"
# 2. 构建Docker镜像
echo "[信息] 构建超轻量Docker镜像 ($TARGET_PLATFORMS)..."
cd "$TEMP_BUILD_DIR"
if [ "$USE_BUILDX" = true ]; then
# 创建并使用buildx构建器实例
echo "[信息] 创建buildx构建器实例..."
docker buildx create --name multiarch-builder --use 2>/dev/null || docker buildx use multiarch-builder 2>/dev/null || true
# 检查是否为多架构构建
if [[ "$TARGET_PLATFORMS" == *","* ]]; then
echo "[信息] 执行多架构构建,这可能需要几分钟时间..."
echo "[提示] 多架构构建会自动推送到本地registry然后再导出"
# 多架构构建需要先推送到registry再导出
# 这里我们使用一个临时的本地registry
echo "[信息] 启动临时本地registry..."
docker run -d --rm --name temp-registry -p 5555:5000 registry:2 2>/dev/null || true
sleep 2
# 构建并推送到临时registry
docker buildx build --platform "$TARGET_PLATFORMS" \
--tag "localhost:5555/$IMAGE_NAME:latest" \
--push .
# 从registry拉取并重新标记
docker pull "localhost:5555/$IMAGE_NAME:latest"
docker tag "localhost:5555/$IMAGE_NAME:latest" "$IMAGE_NAME:latest"
# 清理临时registry
docker stop temp-registry 2>/dev/null || true
else
# 单架构构建可以直接load
echo "[信息] 执行单架构构建..."
docker buildx build --platform "$TARGET_PLATFORMS" --load -t "$IMAGE_NAME:latest" .
fi
else
# 使用传统构建方式
echo "[信息] 使用传统Docker构建..."
docker build --platform "$TARGET_PLATFORMS" -t "$IMAGE_NAME:latest" .
fi
cd - > /dev/null
# 3. 导出Docker镜像
echo "[信息] 导出Docker镜像..."
docker save "$IMAGE_NAME:latest" | gzip > "$EXPORT_DIR/docker-image.tar.gz"
# 4. 创建docker-compose.yml
echo "[信息] 创建docker-compose.yml..."
cat > "$EXPORT_DIR/docker-compose.yml" << 'EOF'
version: '3.8'
services:
dms-compliance-tool:
image: compliance-dms-mini:latest
container_name: dms-compliance-mini
ports:
- "5050:5050" # API服务器端口
- "5051:5051" # 历史查看器端口
volumes:
# 持久化测试报告
- ./test_reports:/app/test_reports
# 持久化上传文件
- ./uploads:/app/uploads
# 持久化日志
- ./logs:/app/logs
# 如果需要自定义配置文件
- ./config:/app/config:ro
environment:
- FLASK_ENV=production
- PYTHONUNBUFFERED=1
- TZ=Asia/Shanghai
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5050/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- dms-network
networks:
dms-network:
driver: bridge
volumes:
test_reports:
uploads:
logs:
EOF
# 5. 创建部署脚本
echo "[信息] 创建部署脚本..."
cat > "$EXPORT_DIR/deploy.sh" << 'EOF'
#!/bin/bash
# DMS合规性测试工具 - Docker Compose版本部署脚本
set -e
echo "=== DMS合规性测试工具 Docker Compose版本部署 ==="
# 检查Docker和Docker Compose
if ! docker info >/dev/null 2>&1; then
echo "[错误] Docker未运行"
exit 1
fi
if ! command -v docker-compose >/dev/null 2>&1 && ! docker compose version >/dev/null 2>&1; then
echo "[错误] Docker Compose未安装"
echo "请安装Docker Compose或使用Docker Desktop"
exit 1
fi
# 创建必要的目录
echo "[信息] 创建数据目录..."
mkdir -p test_reports uploads logs config
# 加载镜像
echo "[信息] 加载Docker镜像..."
docker load < docker-image.tar.gz
# 停止现有服务
echo "[信息] 停止现有服务..."
docker-compose down 2>/dev/null || docker compose down 2>/dev/null || true
# 启动服务
echo "[信息] 启动服务..."
if command -v docker-compose >/dev/null 2>&1; then
docker-compose up -d
else
docker compose up -d
fi
echo "[成功] 部署完成!"
echo "访问地址: http://localhost:5050 (API服务器)"
echo "访问地址: http://localhost:5051 (历史查看器)"
echo ""
echo "管理命令:"
echo "- 查看状态: docker-compose ps"
echo "- 查看日志: docker-compose logs"
echo "- 停止服务: docker-compose down"
echo "- 重启服务: docker-compose restart"
echo ""
echo "数据目录:"
echo "- 测试报告: $(pwd)/test_reports"
echo "- 上传文件: $(pwd)/uploads"
echo "- 日志文件: $(pwd)/logs"
echo "- 配置文件: $(pwd)/config"
EOF
chmod +x "$EXPORT_DIR/deploy.sh"
# 6. 创建README
echo "[信息] 创建README..."
cat > "$EXPORT_DIR/README.md" << 'EOF'
# DMS合规性测试工具 - Docker Compose版本
## 特点
- 基于Alpine Linux镜像体积极小约300MB
- 多阶段构建,优化层结构
- 完全兼容原版架构5050+5051端口
- 使用Docker Compose管理服务
- 支持数据持久化和健康检查
- 支持多架构AMD64 (x86_64) 和 ARM64 (aarch64)
- 兼容Intel/AMD服务器、Apple Silicon Mac、ARM服务器
## 部署方法
1. 解压部署包
2. 运行部署脚本:
```bash
./deploy.sh
```
3. 访问服务:
- API服务器: http://localhost:5050
- 历史查看器: http://localhost:5051
## 管理命令
- 查看服务状态:`docker-compose ps`
- 查看日志:`docker-compose logs`
- 停止服务:`docker-compose down`
- 重启服务:`docker-compose restart`
- 查看实时日志:`docker-compose logs -f`
## 文件说明
- `docker-image.tar.gz` - Docker镜像文件
- `docker-compose.yml` - Docker Compose配置文件
- `deploy.sh` - 一键部署脚本
- `README.md` - 说明文档
## 数据持久化
所有重要数据都会持久化到本地目录:
- `test_reports/` - 测试报告
- `uploads/` - 上传文件
- `logs/` - 日志文件
- `config/` - 配置文件(只读)
EOF
# 7. 显示镜像信息
echo "[信息] Docker镜像信息:"
docker images "$IMAGE_NAME:latest"
# 8. 压缩最终包
echo "[信息] 压缩最终部署包..."
tar -czf "$ARCHIVE_NAME" "$EXPORT_DIR"
# 9. 显示结果
echo ""
echo "=== 创建完成 ==="
echo "部署包: $ARCHIVE_NAME"
echo "部署包大小: $(du -sh "$ARCHIVE_NAME" | cut -f1)"
echo "Docker镜像大小: $(docker images "$IMAGE_NAME:latest" --format "{{.Size}}" 2>/dev/null || echo "约300MB")"
echo ""
echo "部署方法:"
echo "1. 解压: tar -xzf $ARCHIVE_NAME"
echo "2. 进入目录: cd $EXPORT_DIR"
echo "3. 运行: ./deploy.sh"
echo ""
# 清理Docker镜像可选
read -p "是否删除本地Docker镜像(y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker rmi "$IMAGE_NAME:latest"
echo "[信息] 已删除本地Docker镜像"
fi
echo "[完成] Docker Compose版本部署包创建完成"