You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle多项目构建用Jib生成Docker镜像时依赖无法找到

Gradle多项目构建中Jib无法解析Spring Boot依赖的问题

问题场景

在Gradle多项目构建中结合Kotlin与Spring Boot,尝试用Jib为子项目生成Docker镜像时,首个子项目出现依赖无法找到的问题:执行./gradlew bootJar --console=plain可成功构建,但执行./gradlew jibDockerBuild --console=plain失败,报错无法解析:runtimeClasspath的依赖,多个Spring Boot相关依赖找不到,添加--stacktrace后抛出ModuleVersionNotFoundException。

项目结构

project
├── subproject1
|   ├── src
|   |   └── ...
│   └── build.gradle.kts
├── build.gradle.kts
└── settings.gradle.kts

配置文件内容

project/settings.gradle.kts

rootProject.name = "project"
include("subproject1")

project/build.gradle.kts

plugins {
    kotlin("jvm") version "1.8.0"
    id("com.google.cloud.tools.jib") version "3.3.1"
}

jib {
    from {
        image = "eclipse-temurin:17-jre-alpine"
    }
    container {
        user = "myuser:myuser"
        ports = mutableListOf("8080")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(project(":subproject1"))
}

project/subproject1/build.gradle.kts

// mostly taken from start.spring.io
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm")
    kotlin("plugin.spring") version "1.8.0"
    id("org.springframework.boot") version "3.0.5"
    id("io.spring.dependency-management") version "1.1.0"
}

group = "com.example"
version = "1.0"
java.sourceCompatibility = JavaVersion.VERSION_17

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-graphql")
    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.flywaydb:flyway-core")
    implementation("org.flywaydb:flyway-mysql")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    implementation("org.springframework:spring-jdbc")
    implementation("org.apache.commons:commons-collections4:4.4")
    implementation("org.apache.commons:commons-lang3:3.12.0")
    runtimeOnly("org.mariadb:r2dbc-mariadb:1.1.3")
    runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")
    testImplementation("org.springframework.graphql:spring-graphql-test")
    testImplementation("org.springframework.security:spring-security-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

问题原因

你把Jib插件应用在了根项目,但根项目并没有集成Spring Boot的依赖管理机制。子项目subproject1的Spring Boot依赖版本是由io.spring.dependency-management插件统一管理的,这些版本信息只在子项目内生效。当根项目执行Jib任务时,它需要解析自身的runtimeClasspath(其中包含了对子项目的依赖),但根项目没有Spring Boot依赖管理的支持,无法识别子项目中那些未指定具体版本的Spring Boot依赖,从而抛出ModuleVersionNotFoundException。

而bootJar任务能成功,是因为该任务属于子项目的Spring Boot插件,子项目本身能正确解析所有依赖版本。

解决方案

方案一:将Jib插件移到子项目(推荐)

既然是为子项目生成镜像,直接在子项目中配置Jib即可,根项目无需保留Jib相关配置:

修改project/subproject1/build.gradle.kts,添加Jib插件和配置:

plugins {
    kotlin("jvm")
    kotlin("plugin.spring") version "1.8.0"
    id("org.springframework.boot") version "3.0.5"
    id("io.spring.dependency-management") version "1.1.0"
    // 添加Jib插件
    id("com.google.cloud.tools.jib") version "3.3.1"
}

// 添加Jib配置
jib {
    from {
        image = "eclipse-temurin:17-jre-alpine"
    }
    container {
        user = "myuser:myuser"
        ports = mutableListOf("8080")
    }
}

// 其余代码保持不变...

同时修改根项目project/build.gradle.kts,移除Jib相关内容:

plugins {
    kotlin("jvm") version "1.8.0"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(project(":subproject1"))
}

之后执行./gradlew :subproject1:jibDockerBuild --console=plain即可为子项目生成镜像。

方案二:根项目集成Spring Boot依赖管理

如果需要在根项目统一管理Jib配置,可让根项目引入Spring Boot的依赖管理插件,从而识别子项目的依赖版本:

修改根项目project/build.gradle.kts:

plugins {
    kotlin("jvm") version "1.8.0"
    id("com.google.cloud.tools.jib") version "3.3.1"
    // 引入Spring依赖管理插件
    id("io.spring.dependency-management") version "1.1.0"
}

// 导入Spring Boot的依赖管理
dependencyManagement {
    imports {
        mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
    }
}

jib {
    from {
        image = "eclipse-temurin:17-jre-alpine"
    }
    container {
        user = "myuser:myuser"
        ports = mutableListOf("8080")
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(project(":subproject1"))
}

这样根项目就能通过Spring的BOM获取到所有Spring Boot依赖的版本,Jib任务执行时就能正确解析依赖。

关于ModuleVersionNotFoundException的说明

这个异常表示Gradle无法确定某个依赖的具体版本号。通常有两种情况:

  • 依赖声明时没有指定版本,且没有任何依赖管理机制(如Spring BOM、dependency-management插件)提供版本信息;
  • 指定的版本号不存在于配置的仓库中。
    在你的场景中属于第一种情况:根项目没有Spring的依赖管理,无法识别子项目中那些由Spring Boot统一管控版本的依赖。

内容的提问来源于stack exchange,提问作者Kaemmelot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 15:25:01