使用 Palantir Gradle 插件构建 Docker 容器时找不到 .jar 文件

Posted

技术标签:

【中文标题】使用 Palantir Gradle 插件构建 Docker 容器时找不到 .jar 文件【英文标题】:.jar file not found when building a Docker container with Palantir Gradle plug-in 【发布时间】:2018-10-01 04:32:58 【问题描述】:

如果我尝试在 Windows 10 下使用 Spring Boot 应用程序构建 Docker 容器,我会收到以下错误:

> Task :docker FAILED
COPY failed: stat /var/lib/docker/tmp/docker-builder711841135/myproject.jar: no such file or directory

我正在使用版本 18.03.0-ce-win59 (16762) 的 Docker 社区版和带有 Java 8 的 Gradle 4.7。

build.gradle(缩短):

plugins 
    id 'java'
    id 'org.springframework.boot' version '2.0.1.RELEASE'
    id "com.palantir.docker" version "0.19.2"


version = '2.0.0'
sourceCompatibility = 1.8
group = "com.example"

repositories 
    mavenCentral()


bootJar 
    archiveName 'myproject.jar'


dependencies 
    ...


docker 
    dependsOn(build)
    name "$project.group/$jar.baseName"
    files bootJar

Dockerfile(顶层项目目录中 build.gradle 的兄弟):

FROM openjdk:8-jre
COPY build/libs/myproject.jar myproject.jar

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/myproject.jar"]

如果我只使用 Docker(没有 Gradle)构建 Docker 容器,它就可以工作。

如何让 Gradle(或 Docker?)找到 myproject.jar 文件?

【问题讨论】:

你试过COPY build/libs/myproject.jar / 吗? @ThanhNguyenVan 是的,我也试过了,但错误是一样的。源目录好像有问题。 服务器上是否有 build/libs/myproject.jar 文件? 该文件存在于 Gradle 项目的结构中。 “在服务器上”是什么意思?我在我的开发机器上本地运行 Docker 作为 Windows 服务。我有什么事情可以将文件提交到 docker 吗? 文件在这里:C:\Users\me\projects\myproject\trunk\Java\myproject\build\libs\myproject.jar,我从C:\Users\me\projects\myproject\trunk\Java\myproject开始Gradle。 【参考方案1】:

我遇到了类似的问题。这是我花了很多时间后的working solution:-

build.gradle
String imageName = "$project.group/$project.name"
docker 
    //dependsOn build
    dockerfile file('Dockerfile')
    name imageName
    files bootJar.archiveFile.get()
    buildArgs(['JAR_FILE': "$bootJar.archiveFileName.get()"])

dockerRun 
    name "$project.name-container"
    image imageName
    ports '8081:8081'
    env 'SPRING_PROFILES_ACTIVE': 'dev'
    daemonize true
    clean false

Jenkins 文件
FROM adoptopenjdk/openjdk11:alpine-jre

ARG APP_NAME="product-service"
ARG APP_VERSION="0.0.1"
ARG JAR_FILE="/build/libs/$APP_NAME-$APP_VERSION.jar"

COPY $JAR_FILE app.jar
ENTRYPOINT ["java","-jar", "app.jar"]

这适用于 Gradle 任务 :docker:dockerRun。它也适用于 docker 命令行。

【讨论】:

【参考方案2】:

问题在于 Docker 文件中的COPY 命令:

COPY build/libs/myproject.jar myproject.jar

源目录build/libs/ 不是用于构建 Docker 容器的文件所在的位置。相反,目录 build/docker/ 用作 Docker 构建上下文。当COPY 被执行时,这个目录是有效的工作目录。

正确的COPY 命令就这么简单:

COPY myproject.jar /

Docker 任务:

docker 
    dependsOn bootJar
    name "$project.group/$jar.baseName:$version"
    files bootJar.archivePath

如果你也想复制资源,你需要在files参数中添加processResources

files bootJar.archivePath, processResources

【讨论】:

不错,比我的回答更准确。 +1【参考方案3】:

它适用于docker 任务的以下配置:

docker 
    dependsOn build
    name "$project.group/$jar.baseName"
    files bootJar.archivePath
    buildArgs(['JAR_FILE': "$bootJar.archiveName"])

使用这个略有不同的 docker 文件:

FROM openjdk:8-jre
ARG JAR_FILE
COPY $JAR_FILE app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

【讨论】:

【参考方案4】:

这似乎与 palantir/gradle-docker issue 76 一致,它指定:

我根据示例配置了一个新项目,我观察到整个项目(减去build/被复制到build/docker。我会导致不必要的大型 docker 构建上下文。

COPY 应该是build/docker/libs/myproject.jar,或者build/ 本身根本不包括在内。

该问题提到了覆盖另一个 docker 步骤的可能解决方法 - dockerPrepare - 明确准备“build/docker”文件夹。

除了 Dockerfile 之外,我只需要一个 fatJar:

task dockerCopy(type: MoveTo, dependsOn: dockerPrepare) 
    from('build/packed') 
        include "$jarFullName"
    
    into 'build/docker'

【讨论】:

谢谢。但是在我的情况下找不到MoveTo:“无法为根项目获取未知属性'MoveTo'”。但看起来这个问题可以通过 docker 任务的不同配置来解决。我将在这里发布我的解决方案。【参考方案5】:

你的 gradle "destinationDir" 是什么?

生成的 jar 将位于destinationDir/archiveName 中。也许是 target/myproject.jar

所以你应该把:

COPY target/myproject.jar myproject.jar

如果它不起作用,请添加您的 gradle :

destinationDir target

【讨论】:

谢谢。我尝试使用COPY build/libs/myproject.jar myproject.jar 并在bootJar 任务(destinationDir file('target'))和COPY target/myproject.jar myproject.jar 中明确设置destinationDir,但我得到的只是错误消息中的路径略有不同:COPY failed: stat /var/lib/docker/tmp/docker-builder548809975/target/myproject.jar。跨度>

以上是关于使用 Palantir Gradle 插件构建 Docker 容器时找不到 .jar 文件的主要内容,如果未能解决你的问题,请参考以下文章

Android Gradle 插件Gradle 扩展属性 ② ( 定义在根目录 build.gradle 中的扩展属性 | 使用 rootProject.扩展属性名访问 | 扩展属性示例 )

Android Gradle 插件Gradle 扩展属性 ② ( 定义在根目录 build.gradle 中的扩展属性 | 使用 rootProject.扩展属性名访问 | 扩展属性示例 )

Android Gradle 插件Gradle 构建工具简介 ③ ( Gradle 构建脚本编程语言 | Groovy 语言简介 | Groovy 语言特性 )

使用Gradle但不使用Java插件构建Java项目

Android Gradle 插件组件化中的 Gradle 构建脚本实现 ④ ( 使用路由实现组件间通信 | 引入 ARoute 框架 | Gradle 构建脚本优化问题 )

为啥 kotlin gradle 插件无法使用 1.8 目标构建?