Docker离线运行SpringBoot项目Gradle插件找不到问题修复
问题根因
原有配置仅缓存了项目业务代码依赖的jar包,未缓存Gradle第三方插件的依赖包。plugins块中声明的org.springframework.boot属于第三方Gradle插件,默认从Gradle中央插件仓库拉取,断网运行时本地无对应插件缓存,抛出如下错误:
Plugin [id: 'org.springframework.boot', version '2.6.3'] was not found in any of the following sources:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Plugin Repositories (could not resolve plugin artifact 'org.springframework.boot:org.springframework.boot.gradle.plugin:2.6.3') Searched in the following repositories: Gradle Central Plugin Repository
修复方案
实现完全离线运行需要把插件依赖也纳入预下载、本地读取的逻辑,具体修改步骤如下:
1. 新增settings.gradle配置
在项目根目录新建settings.gradle文件,配置插件仓库的离线读取逻辑:
pluginManagement { buildscript { repositories { mavenLocal() def skipDownload = gradle.startParameter.projectProperties.getOrDefault("skipDownload", "false").toBoolean() if (skipDownload) { flatDir { dirs 'pluginlibs' } } else { mavenCentral() gradlePluginPortal() } } dependencies { def skipDownload = gradle.startParameter.projectProperties.getOrDefault("skipDownload", "false").toBoolean() if (skipDownload) { classpath fileTree(dir: 'pluginlibs', include: ['*.jar']) } } } } // 替换为实际项目名称 rootProject.name = 'spring-boot-k8s-service'
2. 修改build.gradle配置
保留原有业务依赖、测试依赖的离线逻辑,新增插件依赖导出任务:
plugins { id 'org.springframework.boot' version '2.6.3' id 'java' } ext { skipDownload = project.hasProperty('skipDownload') ? project.getProperty('skipDownload') as boolean : false } repositories { mavenLocal() if (skipDownload) { flatDir { dirs 'libs' } } else { mavenCentral() } } dependencies { if (skipDownload) { implementation fileTree(dir: 'libs', include: ['*.jar']) testImplementation fileTree(dir: 'testlibs', include: ['*.jar']) } else { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.6.3' } } task getDeps(type: Copy) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE from configurations.compileClasspath into "libs/" from configurations.runtimeClasspath into "libs/" } task getTestDeps(type: Copy) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE from configurations.testCompileClasspath into "testlibs/" from configurations.testRuntimeClasspath into "testlibs/" } // 新增:导出Gradle插件及传递依赖到本地pluginlibs目录 task getPluginDeps(type: Copy) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE from buildscript.configurations.classpath into "pluginlibs/" }
3. 修改Dockerfile配置
在镜像构建阶段新增插件依赖下载步骤,确保所有依赖都在build阶段固化到镜像内:
FROM gradle:7.3-jdk11 WORKDIR /app COPY . . # 联网构建阶段下载所有依赖:业务依赖、测试依赖、Gradle插件依赖 RUN gradle --no-daemon test getDeps getTestDeps getPluginDeps # 默认启动命令:离线执行构建,无需联网 CMD ["sh", "-c", "gradle build -PskipDownload=true"]
验证方法
- 重新构建镜像:执行
docker build -t service-test . - 断开网络后运行容器:执行
docker run --rm -it service-test,即可正常完成离线构建,不会再抛出插件找不到的错误 - 如需离线启动服务调试,执行命令:
docker run --rm -it -p 8080:8080 service-test gradle bootRun -PskipDownload=true
注意事项
- 后续新增第三方Gradle插件时,不需要调整依赖导出逻辑,重新执行docker build即可自动缓存新插件的所有依赖
- 不要修改
skipDownload参数的判断逻辑,确保镜像构建阶段(联网)走远程仓库拉取依赖,容器运行阶段(断网)走本地flatDir读取依赖
内容的提问来源于stack exchange,提问作者Ramanujan R
相关产品推荐
相关产品推荐

