镜像制作
This commit is contained in:
367
build.sh
Normal file
367
build.sh
Normal file
@@ -0,0 +1,367 @@
|
||||
#!/bin/bash
|
||||
|
||||
##############################################
|
||||
# 校园新闻管理系统 - 构建和打包脚本
|
||||
# 功能:
|
||||
# 1. 从git拉取最新代码
|
||||
# 2. 编译后端jar包
|
||||
# 3. 构建前端dist
|
||||
# 4. 制作Docker镜像
|
||||
# 5. 保存镜像到文件(用于离线部署)
|
||||
##############################################
|
||||
|
||||
set -e # 遇到错误立即退出
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
# 项目路径
|
||||
PROJECT_ROOT=$(cd "$(dirname "$0")" && pwd)
|
||||
SERV_PATH="${PROJECT_ROOT}/schoolNewsServ"
|
||||
WEB_PATH="${PROJECT_ROOT}/schoolNewsWeb"
|
||||
DOCKER_PATH="${PROJECT_ROOT}/docker"
|
||||
BUILD_OUTPUT="${PROJECT_ROOT}/build-output"
|
||||
IMAGE_VERSION=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
echo "=========================================="
|
||||
echo "校园新闻管理系统 - 构建脚本"
|
||||
echo "=========================================="
|
||||
log_info "构建版本: ${IMAGE_VERSION}"
|
||||
log_info "项目路径: ${PROJECT_ROOT}"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 创建输出目录
|
||||
mkdir -p "${BUILD_OUTPUT}"
|
||||
|
||||
# ================================================
|
||||
# 步骤1: Git Pull
|
||||
# ================================================
|
||||
log_step "步骤1: 拉取最新代码"
|
||||
cd "${PROJECT_ROOT}"
|
||||
|
||||
# 检查是否有未提交的更改
|
||||
if [[ $(git status --porcelain) ]]; then
|
||||
log_warn "检测到未提交的更改"
|
||||
read -p "是否继续拉取代码?(y/n): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_error "已取消构建"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log_info "从远程仓库拉取代码..."
|
||||
if git pull origin main 2>/dev/null || git pull origin master 2>/dev/null; then
|
||||
log_info "代码拉取完成"
|
||||
else
|
||||
log_warn "代码拉取失败或已是最新版本,继续构建..."
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 步骤2: 构建后端jar包
|
||||
# ================================================
|
||||
log_step "步骤2: 构建后端jar包"
|
||||
cd "${SERV_PATH}"
|
||||
|
||||
log_info "清理旧的构建..."
|
||||
mvn clean -q
|
||||
|
||||
log_info "开始编译后端项目..."
|
||||
log_info "执行: mvn package -DskipTests -pl admin -am"
|
||||
if mvn package -DskipTests -pl admin -am; then
|
||||
log_info "后端编译成功"
|
||||
else
|
||||
log_error "后端编译失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 验证jar包
|
||||
JAR_FILE="${SERV_PATH}/admin/target/admin-1.0.0.jar"
|
||||
if [ -f "${JAR_FILE}" ]; then
|
||||
JAR_SIZE=$(du -h "${JAR_FILE}" | cut -f1)
|
||||
log_info "✅ jar包已生成: ${JAR_SIZE}"
|
||||
log_info " 路径: ${JAR_FILE}"
|
||||
else
|
||||
log_error "❌ jar包未找到"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 步骤3: 构建前端dist
|
||||
# ================================================
|
||||
log_step "步骤3: 构建前端项目"
|
||||
cd "${WEB_PATH}"
|
||||
|
||||
# 检查node_modules
|
||||
if [ ! -d "node_modules" ]; then
|
||||
log_info "安装前端依赖..."
|
||||
npm install
|
||||
fi
|
||||
|
||||
log_info "清理旧的构建..."
|
||||
rm -rf dist
|
||||
|
||||
log_info "开始构建前端项目..."
|
||||
log_info "执行: npm run build"
|
||||
if npm run build; then
|
||||
log_info "前端构建成功"
|
||||
else
|
||||
log_error "前端构建失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 验证dist目录
|
||||
DIST_DIR="${WEB_PATH}/dist"
|
||||
if [ -d "${DIST_DIR}" ]; then
|
||||
DIST_SIZE=$(du -sh "${DIST_DIR}" | cut -f1)
|
||||
FILE_COUNT=$(find "${DIST_DIR}" -type f | wc -l)
|
||||
log_info "✅ dist目录已生成: ${DIST_SIZE} (${FILE_COUNT}个文件)"
|
||||
log_info " 路径: ${DIST_DIR}"
|
||||
else
|
||||
log_error "❌ dist目录未找到"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 步骤4: 制作Docker镜像
|
||||
# ================================================
|
||||
log_step "步骤4: 制作Docker镜像"
|
||||
cd "${PROJECT_ROOT}"
|
||||
|
||||
# 构建MySQL镜像
|
||||
log_info "构建MySQL镜像(包含数据库初始化)..."
|
||||
log_info "执行: docker build -t school-news-mysql:${IMAGE_VERSION} -f docker/Dockerfile.mysql ."
|
||||
if docker build -t school-news-mysql:${IMAGE_VERSION} -f docker/Dockerfile.mysql .; then
|
||||
log_info "✅ MySQL镜像构建成功"
|
||||
docker tag school-news-mysql:${IMAGE_VERSION} school-news-mysql:latest
|
||||
log_info " 镜像标签: school-news-mysql:${IMAGE_VERSION}"
|
||||
log_info " 镜像标签: school-news-mysql:latest"
|
||||
else
|
||||
log_error "❌ MySQL镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 构建后端镜像
|
||||
log_info "构建后端镜像..."
|
||||
log_info "执行: docker build -t school-news-serv:${IMAGE_VERSION} -f docker/Dockerfile.serv ."
|
||||
if docker build -t school-news-serv:${IMAGE_VERSION} -f docker/Dockerfile.serv .; then
|
||||
log_info "✅ 后端镜像构建成功"
|
||||
# 同时打上latest标签
|
||||
docker tag school-news-serv:${IMAGE_VERSION} school-news-serv:latest
|
||||
log_info " 镜像标签: school-news-serv:${IMAGE_VERSION}"
|
||||
log_info " 镜像标签: school-news-serv:latest"
|
||||
else
|
||||
log_error "❌ 后端镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 构建前端镜像
|
||||
log_info "构建前端镜像..."
|
||||
log_info "执行: docker build -t school-news-web:${IMAGE_VERSION} -f docker/Dockerfile.web ."
|
||||
if docker build -t school-news-web:${IMAGE_VERSION} -f docker/Dockerfile.web .; then
|
||||
log_info "✅ 前端镜像构建成功"
|
||||
# 同时打上latest标签
|
||||
docker tag school-news-web:${IMAGE_VERSION} school-news-web:latest
|
||||
log_info " 镜像标签: school-news-web:${IMAGE_VERSION}"
|
||||
log_info " 镜像标签: school-news-web:latest"
|
||||
else
|
||||
log_error "❌ 前端镜像构建失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 查看镜像信息
|
||||
log_info "Docker镜像列表:"
|
||||
docker images | grep -E "school-news-(mysql|serv|web)" | head -10
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 步骤5: 保存镜像到文件
|
||||
# ================================================
|
||||
log_step "步骤5: 保存Docker镜像"
|
||||
cd "${BUILD_OUTPUT}"
|
||||
|
||||
# 保存MySQL镜像
|
||||
MYSQL_IMAGE_FILE="school-news-mysql_${IMAGE_VERSION}.tar"
|
||||
log_info "保存MySQL镜像到文件..."
|
||||
log_info "执行: docker save -o ${MYSQL_IMAGE_FILE} school-news-mysql:${IMAGE_VERSION}"
|
||||
if docker save -o "${MYSQL_IMAGE_FILE}" school-news-mysql:${IMAGE_VERSION}; then
|
||||
MYSQL_SIZE=$(du -h "${MYSQL_IMAGE_FILE}" | cut -f1)
|
||||
log_info "✅ MySQL镜像已保存: ${MYSQL_SIZE}"
|
||||
log_info " 文件: ${BUILD_OUTPUT}/${MYSQL_IMAGE_FILE}"
|
||||
else
|
||||
log_error "❌ MySQL镜像保存失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 保存后端镜像
|
||||
SERV_IMAGE_FILE="school-news-serv_${IMAGE_VERSION}.tar"
|
||||
log_info "保存后端镜像到文件..."
|
||||
log_info "执行: docker save -o ${SERV_IMAGE_FILE} school-news-serv:${IMAGE_VERSION}"
|
||||
if docker save -o "${SERV_IMAGE_FILE}" school-news-serv:${IMAGE_VERSION}; then
|
||||
SERV_SIZE=$(du -h "${SERV_IMAGE_FILE}" | cut -f1)
|
||||
log_info "✅ 后端镜像已保存: ${SERV_SIZE}"
|
||||
log_info " 文件: ${BUILD_OUTPUT}/${SERV_IMAGE_FILE}"
|
||||
else
|
||||
log_error "❌ 后端镜像保存失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 保存前端镜像
|
||||
WEB_IMAGE_FILE="school-news-web_${IMAGE_VERSION}.tar"
|
||||
log_info "保存前端镜像到文件..."
|
||||
log_info "执行: docker save -o ${WEB_IMAGE_FILE} school-news-web:${IMAGE_VERSION}"
|
||||
if docker save -o "${WEB_IMAGE_FILE}" school-news-web:${IMAGE_VERSION}; then
|
||||
WEB_SIZE=$(du -h "${WEB_IMAGE_FILE}" | cut -f1)
|
||||
log_info "✅ 前端镜像已保存: ${WEB_SIZE}"
|
||||
log_info " 文件: ${BUILD_OUTPUT}/${WEB_IMAGE_FILE}"
|
||||
else
|
||||
log_error "❌ 前端镜像保存失败"
|
||||
exit 1
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# 压缩镜像文件(可选)
|
||||
log_info "是否压缩镜像文件?(y/n): "
|
||||
read -p "" -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "压缩镜像文件..."
|
||||
|
||||
if command -v gzip &> /dev/null; then
|
||||
log_info "使用gzip压缩..."
|
||||
gzip -f "${SERV_IMAGE_FILE}"
|
||||
gzip -f "${WEB_IMAGE_FILE}"
|
||||
|
||||
SERV_GZ_SIZE=$(du -h "${SERV_IMAGE_FILE}.gz" | cut -f1)
|
||||
WEB_GZ_SIZE=$(du -h "${WEB_IMAGE_FILE}.gz" | cut -f1)
|
||||
|
||||
log_info "✅ 压缩完成"
|
||||
log_info " 后端: ${SERV_GZ_SIZE} (${SERV_IMAGE_FILE}.gz)"
|
||||
log_info " 前端: ${WEB_GZ_SIZE} (${WEB_IMAGE_FILE}.gz)"
|
||||
else
|
||||
log_warn "gzip未安装,跳过压缩"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 生成部署说明文件
|
||||
# ================================================
|
||||
log_info "生成部署说明文件..."
|
||||
DEPLOY_INFO_FILE="${BUILD_OUTPUT}/部署说明_${IMAGE_VERSION}.txt"
|
||||
|
||||
cat > "${DEPLOY_INFO_FILE}" << EOF
|
||||
========================================
|
||||
校园新闻管理系统 - Docker镜像部署说明
|
||||
========================================
|
||||
|
||||
构建信息:
|
||||
构建时间: $(date '+%Y-%m-%d %H:%M:%S')
|
||||
版本号: ${IMAGE_VERSION}
|
||||
构建主机: $(hostname)
|
||||
Git分支: $(git branch --show-current 2>/dev/null || echo "未知")
|
||||
Git提交: $(git rev-parse --short HEAD 2>/dev/null || echo "未知")
|
||||
|
||||
镜像文件:
|
||||
MySQL镜像: ${MYSQL_IMAGE_FILE}$([ -f "${MYSQL_IMAGE_FILE}.gz" ] && echo ".gz")
|
||||
后端镜像: ${SERV_IMAGE_FILE}$([ -f "${SERV_IMAGE_FILE}.gz" ] && echo ".gz")
|
||||
前端镜像: ${WEB_IMAGE_FILE}$([ -f "${WEB_IMAGE_FILE}.gz" ] && echo ".gz")
|
||||
|
||||
========================================
|
||||
部署步骤:
|
||||
========================================
|
||||
|
||||
1. 将镜像文件传输到目标服务器
|
||||
|
||||
2. 解压镜像文件(如果已压缩):
|
||||
gunzip ${SERV_IMAGE_FILE}.gz
|
||||
gunzip ${WEB_IMAGE_FILE}.gz
|
||||
|
||||
3. 加载Docker镜像:
|
||||
docker load -i ${MYSQL_IMAGE_FILE}
|
||||
docker load -i ${SERV_IMAGE_FILE}
|
||||
docker load -i ${WEB_IMAGE_FILE}
|
||||
|
||||
4. 验证镜像:
|
||||
docker images | grep school-news
|
||||
|
||||
5. 启动服务:
|
||||
cd docker
|
||||
docker-compose up -d
|
||||
|
||||
6. 查看服务状态:
|
||||
docker-compose ps
|
||||
docker-compose logs -f
|
||||
|
||||
========================================
|
||||
访问地址:
|
||||
========================================
|
||||
前端: http://localhost:8080/schoolNewsWeb/
|
||||
后端: http://localhost:8081/schoolNewsServ
|
||||
|
||||
========================================
|
||||
注意事项:
|
||||
========================================
|
||||
1. 确保目标服务器已安装Docker和Docker Compose
|
||||
2. 确保端口8080、8081、3306、6379未被占用
|
||||
3. 首次部署需要准备数据库初始化脚本
|
||||
4. 生产环境请修改默认密码(.env文件)
|
||||
|
||||
========================================
|
||||
EOF
|
||||
|
||||
log_info "✅ 部署说明已生成: ${DEPLOY_INFO_FILE}"
|
||||
echo ""
|
||||
|
||||
# ================================================
|
||||
# 构建摘要
|
||||
# ================================================
|
||||
echo "=========================================="
|
||||
echo "构建完成!"
|
||||
echo "=========================================="
|
||||
log_info "构建版本: ${IMAGE_VERSION}"
|
||||
echo ""
|
||||
log_info "Docker镜像:"
|
||||
echo " - school-news-mysql:${IMAGE_VERSION}"
|
||||
echo " - school-news-serv:${IMAGE_VERSION}"
|
||||
echo " - school-news-web:${IMAGE_VERSION}"
|
||||
echo ""
|
||||
log_info "镜像文件保存在: ${BUILD_OUTPUT}/"
|
||||
ls -lh "${BUILD_OUTPUT}/" | grep -E "(tar|gz|txt)" | awk '{print " - "$9" ("$5")"}'
|
||||
echo ""
|
||||
log_info "下一步操作:"
|
||||
echo " 1. 查看部署说明: cat ${DEPLOY_INFO_FILE}"
|
||||
echo " 2. 传输镜像文件到目标服务器"
|
||||
echo " 3. 在目标服务器加载镜像: docker load -i <镜像文件>"
|
||||
echo " 4. 启动服务: cd docker && docker-compose up -d"
|
||||
echo "=========================================="
|
||||
Reference in New Issue
Block a user