springboot项目,linux脚本,java项目一键拉取git,maven打包,部署docker镜像
·
适配国内镜像和maven仓库等(秒级构建速度)
springboot+maven+jdk1.8的项目结构:
适合公司资源有限,无法使用ci/cd工具的情况,可以自己按照脚本进行修改(容器化)
默认Dockerfile在项目根目录,也可以指定
基本包含常用的java开发使用的docker常规场景
优缺点:
优点:一键启动就能自动拉取代码,maven打包,构建docker镜像和部署服务
缺点:环境不同,需要根据自己的实际情况进行修改
脚本分为常规版和简化版:
有详细的注释
docker-build-java-maven.sh(常规版)
simple-docker-java-maven.sh(简化版)
主要流程如下:
1.自动拉取配置git仓库代码
2.基于本地服务器或者docker-maven两种构建方式可配置
3.构建docker镜像
4.部署docker容器
docker-build-java-maven.sh
#!/bin/bash
# docker-build-java-maven.sh - 支持Java Maven构建的Docker构建脚本
set -e # 遇到错误立即退出
#first use local maven
# 默认变量
DOCKERFILE="Dockerfile"
IMAGE_NAME="my-java-app"
CONTAINER_NAME="my-java-app-container"
TAG="latest"
PORT="8080"
BUILD_CONTEXT="."
GIT_REPO=""
GIT_BRANCH="main"
GIT_DIR="/tmp/docker-build-$(date +%s)"
KEEP_GIT_CLONE=false
MAVEN_CMD="mvn"
MAVEN_GOALS="clean package"
MAVEN_PROFILE=""
SKIP_TESTS=false
BUILD_ARTIFACT_DIR="target"
JAR_FILE_PATTERN="*.jar"
USE_DOCKER_MAVEN=false
#
MAVEN_DOCKER_IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/maven:3.8.6-openjdk-8"
#
JAVA_DOCKER_IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/openjdk:8-alpine"
# 清理函数
cleanup() {
if [[ "$KEEP_GIT_CLONE" != "true" && -d "$GIT_DIR" ]]; then
echo "清理Git临时目录: $GIT_DIR"
rm -rf "$GIT_DIR"
fi
}
# 信号处理
trap cleanup EXIT INT TERM
# 显示帮助信息
usage() {
echo "用法: $0 [选项]"
echo "选项:"
echo " -f, --file FILE 指定Dockerfile路径 (默认: ./Dockerfile)"
echo " -i, --image NAME 指定镜像名称 (默认: my-java-app)"
echo " -c, --container NAME 指定容器名称 (默认: my-java-app-container)"
echo " -t, --tag TAG 指定镜像标签 (默认: latest)"
echo " -p, --port PORT 指定端口映射 (默认: 8080)"
echo " -b, --build-only 仅构建镜像,不运行容器"
echo " -r, --run-only 仅运行容器,不重新构建"
echo " -d, --detach 在后台运行容器"
echo " --context PATH 构建上下文路径 (默认: .)"
echo " --git-repo URL Git仓库URL"
echo " --git-branch BRANCH Git分支 (默认: main)"
echo " --git-dir DIR 本地Git目录路径"
echo " --keep-git-clone 保留Git克隆目录"
echo " --maven-cmd CMD Maven命令 (默认: mvn)"
echo " --maven-goals GOALS Maven目标 (默认: clean package)"
echo " --maven-profile PROFILE Maven profile"
echo " --skip-tests 跳过测试"
echo " --artifact-dir DIR 构建产物目录 (默认: target)"
echo " --jar-pattern PATTERN JAR文件匹配模式 (默认: *.jar)"
echo " --use-docker-maven 使用Docker内的Maven进行构建"
echo " --maven-image IMAGE Maven Docker镜像 (默认: maven:3.8.6-openjdk-17)"
echo " --java-image IMAGE Java运行环境镜像 (默认: openjdk:17-jre-slim)"
echo " --rm 容器退出时自动删除"
echo " --env KEY=VALUE 设置环境变量"
echo " --volume HOST:CONTAINER 挂载卷"
echo " -h, --help 显示此帮助信息"
echo ""
echo "示例:"
echo " $0 --git-repo https://github.com/user/myapp.git --maven-goals 'clean package'"
echo " $0 --maven-profile prod --skip-tests"
echo " $0 --use-docker-maven --maven-image maven:3.8.6-openjdk-11"
}
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-f|--file)
DOCKERFILE="$2"
shift 2
;;
-i|--image)
IMAGE_NAME="$2"
shift 2
;;
-c|--container)
CONTAINER_NAME="$2"
shift 2
;;
-t|--tag)
TAG="$2"
shift 2
;;
-p|--port)
PORT="$2"
shift 2
;;
-b|--build-only)
BUILD_ONLY=true
shift
;;
-r|--run-only)
RUN_ONLY=true
shift
;;
-d|--detach)
DETACH=true
shift
;;
--context)
BUILD_CONTEXT="$2"
shift 2
;;
--git-repo)
GIT_REPO="$2"
shift 2
;;
--git-branch)
GIT_BRANCH="$2"
shift 2
;;
--git-dir)
GIT_DIR="$2"
KEEP_GIT_CLONE=true
shift 2
;;
--keep-git-clone)
KEEP_GIT_CLONE=true
shift
;;
--maven-cmd)
MAVEN_CMD="$2"
shift 2
;;
--maven-goals)
MAVEN_GOALS="$2"
shift 2
;;
--maven-profile)
MAVEN_PROFILE="$2"
shift 2
;;
--skip-tests)
SKIP_TESTS=true
shift
;;
--artifact-dir)
BUILD_ARTIFACT_DIR="$2"
shift 2
;;
--jar-pattern)
JAR_FILE_PATTERN="$2"
shift 2
;;
--use-docker-maven)
USE_DOCKER_MAVEN=true
shift
;;
--maven-image)
MAVEN_DOCKER_IMAGE="$2"
shift 2
;;
--java-image)
JAVA_DOCKER_IMAGE="$2"
shift 2
;;
--rm)
RM_CONTAINER=true
shift
;;
--env)
ENV_VARS+=("$2")
shift 2
;;
--volume)
VOLUMES+=("$2")
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "未知选项: $1"
usage
exit 1
;;
esac
done
# 检查必要工具是否安装
check_dependencies() {
local deps=("docker")
if [[ -n "$GIT_REPO" ]]; then
deps+=("git")
fi
# 如果不使用Docker Maven,检查本地Maven
if [[ "$USE_DOCKER_MAVEN" != true ]]; then
if ! command -v "$MAVEN_CMD" &> /dev/null; then
echo "错误: 未找到 Maven,请先安装或使用 --use-docker-maven 选项"
exit 1
fi
fi
for dep in "${deps[@]}"; do
if ! command -v "$dep" &> /dev/null; then
echo "错误: 未找到 $dep,请先安装"
exit 1
fi
done
# 检查Docker守护进程是否运行
if ! docker info > /dev/null 2>&1; then
echo "错误: Docker守护进程未运行"
exit 1
fi
}
# 克隆Git仓库
clone_git_repo() {
echo "正在克隆Git仓库..."
echo "仓库URL: $GIT_REPO"
echo "分支: $GIT_BRANCH"
echo "目标目录: $GIT_DIR"
# 创建目录
mkdir -p "$GIT_DIR"
# 克隆仓库
if git clone --branch "$GIT_BRANCH" --depth 1 "$GIT_REPO" "$GIT_DIR"; then
echo "✅ Git仓库克隆成功"
# 显示最新提交信息
echo "最新提交:"
cd "$GIT_DIR" && git log --oneline -1 && cd - > /dev/null
# 更新构建上下文
BUILD_CONTEXT="$GIT_DIR"
else
echo "❌ Git仓库克隆失败"
exit 1
fi
}
# 检查是否是Maven项目
is_maven_project() {
if [[ -f "$BUILD_CONTEXT/pom.xml" ]]; then
return 0
else
return 1
fi
}
# 使用本地Maven构建
build_with_local_maven() {
echo "使用本地Maven构建项目..."
local original_dir=$(pwd)
cd "$BUILD_CONTEXT"
# 构建Maven命令
local maven_cmd="$MAVEN_CMD $MAVEN_GOALS"
# 添加profile
if [[ -n "$MAVEN_PROFILE" ]]; then
maven_cmd+=" -P$MAVEN_PROFILE"
fi
# 跳过测试
if [[ "$SKIP_TESTS" == true ]]; then
maven_cmd+=" -DskipTests"
fi
echo "执行Maven命令: $maven_cmd"
eval "$maven_cmd"
if [[ $? -eq 0 ]]; then
echo "✅ Maven构建成功"
# 显示构建产物
if [[ -d "$BUILD_ARTIFACT_DIR" ]]; then
echo "构建产物:"
ls -la "$BUILD_ARTIFACT_DIR"/$JAR_FILE_PATTERN 2>/dev/null || echo "未找到JAR文件"
fi
else
echo "❌ Maven构建失败"
exit 1
fi
cd "$original_dir"
}
# 使用Docker Maven构建
build_with_docker_maven() {
echo "使用Docker Maven构建项目..."
# 确保GIT_DIR存在
mkdir -p "$GIT_DIR"
# 创建settings.xml文件
local settings_file="$GIT_DIR/settings.xml"
cat > "$settings_file" << EOF
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
EOF
# 准备Maven命令
local maven_cmd="$MAVEN_GOALS"
# 添加profile
if [[ -n "$MAVEN_PROFILE" ]]; then
maven_cmd+=" -P$MAVEN_PROFILE"
fi
# 跳过测试
if [[ "$SKIP_TESTS" == true ]]; then
maven_cmd+=" -DskipTests"
fi
# 创建Docker运行命令
local docker_cmd="docker run --rm"
docker_cmd+=" -v \"$BUILD_CONTEXT\":/usr/src/app"
docker_cmd+=" -v \"$GIT_DIR/settings.xml\":/root/.m2/settings.xml"
docker_cmd+=" -v \"/tmp/maven-repo\":/root/.m2/repository"
docker_cmd+=" -w /usr/src/app"
docker_cmd+=" $MAVEN_DOCKER_IMAGE"
docker_cmd+=" mvn $maven_cmd"
echo "执行Docker Maven命令: $docker_cmd"
eval "$docker_cmd"
if [[ $? -eq 0 ]]; then
echo "✅ Docker Maven构建成功"
# 显示构建产物
if [[ -d "$BUILD_CONTEXT/$BUILD_ARTIFACT_DIR" ]]; then
echo "构建产物:"
ls -la "$BUILD_CONTEXT/$BUILD_ARTIFACT_DIR"/$JAR_FILE_PATTERN 2>/dev/null || echo "未找到JAR文件"
fi
else
echo "❌ Docker Maven构建失败"
exit 1
fi
}
# 执行Maven构建
run_maven_build() {
if ! is_maven_project; then
echo "⚠️ 未找到pom.xml,跳过Maven构建"
return 0
fi
echo "检测到Maven项目,开始构建..."
echo "项目目录: $BUILD_CONTEXT"
if [[ "$USE_DOCKER_MAVEN" == true ]]; then
build_with_docker_maven
else
build_with_local_maven
fi
}
# 生成Dockerfile(如果不存在)
generate_dockerfile() {
local dockerfile_path="$BUILD_CONTEXT/$DOCKERFILE"
if [[ ! -f "$dockerfile_path" ]]; then
echo "未找到Dockerfile,自动生成..."
# 查找JAR文件
local jar_file=$(find "$BUILD_CONTEXT/$BUILD_ARTIFACT_DIR" -name "$JAR_FILE_PATTERN" 2>/dev/null | head -1)
if [[ -z "$jar_file" ]]; then
echo "❌ 未找到JAR文件,无法自动生成Dockerfile"
return 1
fi
local jar_name=$(basename "$jar_file")
cat > "$dockerfile_path" << EOF
FROM $JAVA_DOCKER_IMAGE
WORKDIR /app
# 复制JAR文件
COPY $BUILD_ARTIFACT_DIR/$jar_name app.jar
# 创建非root用户
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
# 暴露端口
EXPOSE 8080
# 启动应用
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
EOF
echo "✅ 已生成Dockerfile: $dockerfile_path"
echo "=== 生成的Dockerfile内容 ==="
cat "$dockerfile_path"
echo "============================"
fi
}
# 检查Dockerfile是否存在
check_dockerfile() {
local dockerfile_path
if [[ "$DOCKERFILE" == /* ]]; then
# 绝对路径
dockerfile_path="$DOCKERFILE"
else
# 相对路径(相对于构建上下文)
dockerfile_path="$BUILD_CONTEXT/$DOCKERFILE"
fi
if [[ ! -f "$dockerfile_path" ]]; then
echo "❌ Dockerfile不存在: $dockerfile_path"
# 尝试自动生成
if ! generate_dockerfile; then
# 显示构建上下文中的文件
if [[ -d "$BUILD_CONTEXT" ]]; then
echo "构建上下文 ($BUILD_CONTEXT) 中的文件:"
ls -la "$BUILD_CONTEXT" | head -10
fi
exit 1
fi
fi
}
# 构建Docker镜像
build_docker_image() {
echo "正在构建Docker镜像..."
echo "Dockerfile: $DOCKERFILE"
echo "构建上下文: $BUILD_CONTEXT"
echo "镜像名称: $IMAGE_NAME:$TAG"
# 构建命令
local build_cmd="docker build"
build_cmd+=" -f \"$BUILD_CONTEXT/$DOCKERFILE\""
build_cmd+=" -t \"$IMAGE_NAME:$TAG\""
# 添加构建参数
build_cmd+=" --build-arg JAVA_IMAGE=$JAVA_DOCKER_IMAGE"
build_cmd+=" \"$BUILD_CONTEXT\""
echo "执行命令: $build_cmd"
eval "$build_cmd"
if [[ $? -eq 0 ]]; then
echo "✅ 镜像构建成功: $IMAGE_NAME:$TAG"
else
echo "❌ 镜像构建失败"
exit 1
fi
}
# 停止并删除现有容器
cleanup_container() {
if docker ps -a | grep -q "$CONTAINER_NAME"; then
echo "发现已存在的容器: $CONTAINER_NAME"
read -p "是否停止并删除现有容器? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
echo "✅ 容器已清理"
else
echo "⚠️ 保留现有容器"
# 询问是否重命名新容器
read -p "是否重命名新容器? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
CONTAINER_NAME="${CONTAINER_NAME}-$(date +%s)"
echo "新容器名称: $CONTAINER_NAME"
else
echo "错误: 容器名称冲突"
exit 1
fi
fi
fi
}
# 运行Docker容器
run_container() {
echo "正在启动容器..."
# 构建运行命令
local run_cmd="docker run"
# 容器名称
run_cmd+=" --name $CONTAINER_NAME"
# 端口映射
if [[ -n "$PORT" ]]; then
run_cmd+=" -p $PORT"
fi
# 后台运行
if [[ "$DETACH" == true ]]; then
run_cmd+=" -d"
else
run_cmd+=" -it"
fi
# 自动删除容器
if [[ "$RM_CONTAINER" == true ]]; then
run_cmd+=" --rm"
fi
# 环境变量
for env_var in "${ENV_VARS[@]}"; do
run_cmd+=" -e $env_var"
done
# 卷挂载
for volume in "${VOLUMES[@]}"; do
run_cmd+=" -v $volume"
done
# Java特定环境变量
run_cmd+=" -e JAVA_OPTS=\"-Xmx512m -Xms256m\""
# 镜像名称
run_cmd+=" $IMAGE_NAME:$TAG"
echo "执行命令: $run_cmd"
eval "$run_cmd"
if [[ $? -eq 0 ]]; then
if [[ "$DETACH" == true ]]; then
echo "✅ 容器已在后台启动: $CONTAINER_NAME"
echo "查看日志: docker logs $CONTAINER_NAME"
echo "进入容器: docker exec -it $CONTAINER_NAME bash"
echo "停止容器: docker stop $CONTAINER_NAME"
else
echo "✅ 容器执行完成"
fi
else
echo "❌ 容器启动失败"
exit 1
fi
}
# 显示构建信息
show_build_info() {
echo ""
echo "=== 构建信息 ==="
echo "镜像: $IMAGE_NAME:$TAG"
echo "容器: $CONTAINER_NAME"
echo "Java镜像: $JAVA_DOCKER_IMAGE"
if [[ -n "$GIT_REPO" ]]; then
echo "Git仓库: $GIT_REPO ($GIT_BRANCH)"
fi
if is_maven_project; then
echo "Maven构建: $MAVEN_GOALS"
if [[ -n "$MAVEN_PROFILE" ]]; then
echo "Maven Profile: $MAVEN_PROFILE"
fi
if [[ "$SKIP_TESTS" == true ]]; then
echo "跳过测试: 是"
fi
fi
if [[ -n "$PORT" ]]; then
echo "端口映射: $PORT"
fi
echo ""
}
# 主函数
main() {
echo "=== Java Maven Docker构建脚本 ==="
# 检查依赖
check_dependencies
# 如果指定了Git仓库,则克隆
if [[ -n "$GIT_REPO" ]]; then
clone_git_repo
fi
# 构建模式判断
if [[ "$RUN_ONLY" != true ]]; then
# 执行Maven构建
run_maven_build
# 检查/生成Dockerfile
check_dockerfile
# 构建Docker镜像
build_docker_image
fi
# 运行模式判断
if [[ "$BUILD_ONLY" != true ]]; then
cleanup_container
run_container
fi
# 显示信息
show_build_info
echo "=== 脚本执行完成 ==="
}
# 执行主函数
main "$@"
docker-build-java-maven.sh启动命令示例(脚本中有详细参数使用):
支持本地maven打包或者docker-maven打包(见代码)
指定仓库地址:--git-repo http://127.0.0.1:3000/XXXX/xx.git
指定代码仓库分支 --git-branch master -d
./docker-build-java-maven.sh --git-repo http://127.0.0.1:3000/XXXX/xx.git --git-branch master -d
simple-docker-java-maven.sh
#!/bin/bash
# simple-docker-java-maven.sh - 简化版Java Maven Docker构建脚本
set -e
GIT_REPO="$1"
IMAGE_NAME="${2:-my-java-app}"
CONTAINER_NAME="${3:-java-app}"
PORT="${4:-8080:8080}"
BRANCH="${5:-main}"
PROFILE="${6:-}"
if [[ -z "$GIT_REPO" ]]; then
echo "用法: $0 <git-repo> [image-name] [container-name] [port] [branch] [profile]"
echo "示例: $0 https://github.com/user/myapp.git myapp java-app 8080:8080 main prod"
exit 1
fi
TEMP_DIR="/tmp/java-build-$(date +%s)"
# 清理函数
cleanup() {
echo "清理临时目录: $TEMP_DIR"
rm -rf "$TEMP_DIR"
}
trap cleanup EXIT
echo "🔧 克隆Git仓库..."
git clone --branch "$BRANCH" --depth 1 "$GIT_REPO" "$TEMP_DIR"
echo "📦 Maven构建..."
cd "$TEMP_DIR"
# 构建命令
MAVEN_CMD="mvn clean package -DskipTests"
if [[ -n "$PROFILE" ]]; then
MAVEN_CMD+=" -P$PROFILE"
fi
echo "执行: $MAVEN_CMD"
eval "$MAVEN_CMD"
# 查找JAR文件
JAR_FILE=$(find target -name "*.jar" | head -1)
if [[ -z "$JAR_FILE" ]]; then
echo "❌ 未找到JAR文件"
exit 1
fi
echo "✅ 找到JAR文件: $JAR_FILE"
echo "🐳 构建Docker镜像..."
cat > Dockerfile << EOF
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/openjdk:8-alpine
WORKDIR /app
COPY $JAR_FILE app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
EOF
docker build -t "$IMAGE_NAME" .
echo "🚀 启动容器..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
docker run -d --name "$CONTAINER_NAME" -p "$PORT" "$IMAGE_NAME"
echo "✅ 部署完成!"
echo "📊 容器状态: docker ps | grep $CONTAINER_NAME"
echo "📋 查看日志: docker logs $CONTAINER_NAME"
echo "🔗 应用地址: http://localhost:${PORT%:*}"
simple-docker-java-maven.sh启动命令示例(脚本中有详细参数使用):
需要服务器安装maven
仓库地址 名称 容器名称 端口映射 分支 环境
http://127.0.0.1:3000/XXXX/xx.git myapp myapp-container 8183:8080 main prod
./simple-docker-java-maven.sh http://127.0.0.1:3000/XXXX/xx.git myapp myapp-container 8183:8080 main prod
更多推荐



所有评论(0)