适配国内镜像和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

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐