gradle docker plugin bmuschko 将 build.gradle 拆分为两个文件会出错

Posted

技术标签:

【中文标题】gradle docker plugin bmuschko 将 build.gradle 拆分为两个文件会出错【英文标题】:gradle docker plugin bmuschko Splitting a build.gradle into two files gives error 【发布时间】:2018-10-28 07:53:10 【问题描述】:

我不熟悉使用 gradle 脚本。我有一个 build.gradle 文件,我想将其拆分为两个文件。拆分较大的 build.gradle 文件后,我得到以下两个文件。

build.gradle

buildscript 
    ext 
        springBootVersion = '1.5.12.RELEASE'
        gradleDockerVersion = '3.2.7'
    
    repositories 
        jcenter()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
        classpath("com.bmuschko:gradle-docker-plugin:$gradleDockerVersion")
    


apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

jar 
    baseName = 'gs-spring-boot'
    version =  '0.1.0'


repositories 
    mavenCentral()


sourceCompatibility = 1.8
targetCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'

dependencies 
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("junit:junit")

project.ext.imageName = 'myImage'
project.ext.tagName ='myTag'
project.ext.jarName = (jar.baseName + '-' + jar.version).toLowerCase()

apply from: 'dockerapp.gradle'

dockerapp.gradle

def gradleDockerVersion = '3.7.2'
buildscript 
    repositories 
        jcenter()
    
    dependencies 
        classpath("com.bmuschko:gradle-docker-plugin:$gradleDockerVersion")
    


apply plugin: 'com.bmuschko.docker-remote-api'

import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
import com.bmuschko.gradle.docker.tasks.image.DockerRemoveImage
import com.bmuschko.gradle.docker.tasks.image.Dockerfile

def imageName = project.ext.imageName
def tagName = project.ext.tagName
def jarName = project.ext.jarName

task createAppDockerfile(type: Dockerfile) 
    // Don't create dockerfile if file already exists
    onlyIf  !project.file('Dockerfile').exists() 
    group 'Docker'
    description 'Generate docker file for the application'
    dependsOn bootRepackage
    destFile = project.file('Dockerfile')
    String dockerProjFolder = project.projectDir.name
    from 'openjdk:8-jre-slim'
    runCommand("mkdir -p /app/springboot/$dockerProjFolder && mkdir -p /app/springboot/$dockerProjFolder/conf")
    addFile("./build/libs/$jarName.jar", "/app/springboot/$dockerProjFolder/")
    environmentVariable('CATALINA_BASE', "/app/springboot/$dockerProjFolder")
    environmentVariable('CATALINA_HOME', "/app/springboot/$dockerProjFolder")
    workingDir("/app/springboot/$dockerProjFolder")
    if (System.properties.containsKey('debug')) 
        entryPoint('java', '-Xdebug', '-Xrunjdwp:server=y,transport=dt_socket,address=5005,suspend=n', '-jar', "/app/springboot/$dockerProjFolder/$jarName.jar")
     else 
        entryPoint('java', '-jar', "/app/springboot/$dockerProjFolder/$jarName.jar")
    


task removeAppImage(type: DockerRemoveImage) 
    group 'Docker'
    description 'Remove the docker image using force'
    force = true
    targetImageId  imageName 
    onError  exception ->
        if (exception.message.contains('No such image')) 
            println 'Docker image not found for the current project.'
        
    


task createAppImage(type: DockerBuildImage) 
    group 'Docker'
    description 'Executes bootRepackage, generates a docker file and builds image from it'
    dependsOn(createAppDockerfile, removeAppImage)
    dockerFile = createAppDockerfile.destFile
    inputDir = dockerFile.parentFile
    if (tagName)
        tag = "$tagName"
    else if (imageName)
        tag = "$imageName"
    else
        tag = "$jarName"

如果我尝试运行命令./gradlew createAppImage,我会收到如下错误:

dockerapp.gradle 文件中的其他两个任务似乎没有问题。如果我将所有代码都放在 build.gradle 文件中,它可以正常工作而不会出现任何错误。拆分文件并执行 createAppImage 而不出错的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我能够在 CDancy(插件的维护者)的帮助下解决这个问题,如下所示:

build.gradle

buildscript 
    ext 
        springBootVersion = '1.5.12.RELEASE'
        gradleDockerVersion = '3.2.7'
    
    repositories 
        jcenter()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
        classpath("com.bmuschko:gradle-docker-plugin:$gradleDockerVersion")
    
    

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'    

jar 
    baseName = 'gs-spring-boot'
    version =  '0.1.0'
    

repositories 
    mavenCentral()
    

sourceCompatibility = 1.8
targetCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'    

dependencies 
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("junit:junit")

project.ext.imageName = 'myimage'
project.ext.tagName ='mytag'
project.ext.jarName = (jar.baseName + '-' + jar.version).toLowerCase()    

apply from: 'docker.gradle'

docker.gradle

buildscript 
    repositories 
        jcenter()
    
    dependencies 
        classpath 'com.bmuschko:gradle-docker-plugin:3.2.7'
    

repositories 
    jcenter()

// use fully qualified class name
apply plugin: com.bmuschko.gradle.docker.DockerRemoteApiPlugin    

// import task classes
import com.bmuschko.gradle.docker.tasks.image.*    

def imageName = project.ext.imageName
def tagName = project.ext.tagName
def jarName = project.ext.jarName    

task createAppDockerfile(type: Dockerfile) 
    // Don't create dockerfile if file already exists
    onlyIf  !project.file('Dockerfile').exists() 
    group 'Docker'
    description 'Generate docker file for the application'
    dependsOn bootRepackage
    destFile = project.file('Dockerfile')
    String dockerProjFolder = project.projectDir.name
    from 'openjdk:8-jre-slim'
    runCommand("mkdir -p /app/springboot/$dockerProjFolder && mkdir -p /app/springboot/$dockerProjFolder/conf")
    addFile("./build/libs/$jarName.jar", "/app/springboot/$dockerProjFolder/")
    environmentVariable('CATALINA_BASE', "/app/springboot/$dockerProjFolder")
    environmentVariable('CATALINA_HOME', "/app/springboot/$dockerProjFolder")
    workingDir("/app/springboot/$dockerProjFolder")
    if (System.properties.containsKey('debug')) 
        entryPoint('java', '-Xdebug', '-Xrunjdwp:server=y,transport=dt_socket,address=5005,suspend=n', '-jar', "/app/springboot/$dockerProjFolder/$jarName.jar")
     else 
        entryPoint('java', '-jar', "/app/springboot/$dockerProjFolder/$jarName.jar")
    
    

task removeAppImage(type: DockerRemoveImage) 
    group 'Docker'
    description 'Remove the docker image using force'
    force = true
    targetImageId  imageName 
    onError  exception ->
        if (exception.message.contains('No such image')) 
            println 'Docker image not found for the current project.'
         else 
            print exception
        
    
    

task createAppImage(type: DockerBuildImage) 
    group 'Docker'
    description 'Executes bootRepackage, generates a docker file and builds image from it'
    dependsOn(createAppDockerfile, removeAppImage)
    dockerFile = createAppDockerfile.destFile
    inputDir = dockerFile.parentFile
    if (tagName)
        tag = "$tagName"
    else if (imageName)
        tag = "$imageName"
    else
        tag = "$jarName"

更改基本上在我的 docker.gradle 文件中,我必须添加指向 jcenter() 的存储库部分并使用完全限定的插件类名。

【讨论】:

【参考方案2】:

我想知道您为什么要在 Gradle 中使用 Docker 插件?在与维护最多的Mushko's Gradle Docker Plugin 玩了一段时间后,我不明白为什么要以不同的语法构建 plugin 样板而不是 docker 样板

Gradle 中的容器化对程序员来说很舒服,DevOps 会说他们不像这样使用 Docker,如果你需要支持,你应该按照他们的方式去做。我在下面找到了一个简短、纯 Docker 风格且功能齐全的解决方案

在项目结构中找到正常的Dockerfile和docker.sh shell脚本:

在您的build.gradle 文件中:

    buildscript 
        repositories 
            gradlePluginPortal()
        
    

    plugins 
        id 'java'
        id 'application'
    

    // Entrypoint:

    jar 
        manifest 
            attributes 'Main-Class': 'com.example.Test'
        
    

    mainClassName = 'com.example.Test'

    // Run in DOCKER-container:

    task runInDockerContainer 
        doLast 
            exec 
                workingDir '.' // Relative to project's root folder.
                commandLine 'sh', './build/resources/main/docker.sh'
            
    //        exec 
    //            workingDir "."
    //            commandLine 'sh', './build/resources/main/other.sh'
    //        
        
    

按照正常的 Docker 文档在干净的 shell 脚本中做任何你想做的事情:

    # Everything is run relative to project's root folder:

    # Put everything together into build/docker folder for DOCKER-build:
    if [ -d "build/docker" ]; then rm -rf build/docker; fi;
    mkdir build/docker;
    cp build/libs/test.jar build/docker/test.jar;
    cp build/resources/main/Dockerfile build/docker/Dockerfile;

    # Build image from files in build/docker:
    cd build/docker || exit;
    docker build . -t test;

    # Run container based on image:
    echo $PWD
    docker run test;

【讨论】:

在您的情况下,拥有一个静态 Dockerfile 就可以了。在其他情况下,您可能希望利用 Gradle 的“dependsOn”命令动态构建 Dockerfile,其内容可能会根据项目中的其他依赖项而更改。我以这种方式设置为在单个主项目中构建 6 个 docker,并且我的 docker 仅在它们的依赖项发生更改时才构建。它非常高效,无需将 Gradle 任务与 shell 脚本混合使用。

以上是关于gradle docker plugin bmuschko 将 build.gradle 拆分为两个文件会出错的主要内容,如果未能解决你的问题,请参考以下文章

基于jib-maven-plugin快速构建微服务docker镜像

如何升级gradle plugin

gradle wrapper, gradle ,gradle plugin 之间的关系

gradle/gradle plugin/Android studio关系

Gradle之Android Gradle Plugin 主要 Task 分析

Android Gradle 5.0 更新:原因:org.jetbrains.plugins.gradle.tooling.util