无法在 Heroku 上部署我的 Grails 3 应用程序

Posted

技术标签:

【中文标题】无法在 Heroku 上部署我的 Grails 3 应用程序【英文标题】:Unable to deploy my Grails 3 app on Heroku 【发布时间】:2017-09-04 16:36:51 【问题描述】:

我正在尝试在 Heroku 上部署我的 Grails 3 应用程序。

我参考了this blog,并遵循了每一步,但是当我尝试运行git push heroku master 命令时,会产生以下输出。

remote:        FAILURE: Build failed with an exception.
remote:        
remote:        * What went wrong:
remote:        Task 'stage' not found in root project 'build_6ce46a3ec9d8cecee177ef2d3589c9f1'.
remote:        
remote:        * Try:
remote:        Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
remote:        
remote:        BUILD FAILED
remote:        
remote:        Total time: 1 mins 2.541 secs
remote: 
remote:  !     ERROR: Failed to run Gradle!
remote:        It looks like your project does not contain a 'stage' task, which Heroku needs in order
remote:        to build your app. Our Dev Center article on preparing a Gradle application for Heroku
remote:        describes how to create this task:
remote:        https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku
remote:        
remote:        If you're stilling having trouble, please submit a ticket so we can help:
remote:        https://help.heroku.com
remote:        
remote:        Thanks,
remote:        Heroku
remote: 
remote:  !     Push rejected, failed to compile Gradle app.
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !   Push rejected to employeedatabase.
remote: 

所以根据输出,我参考了 Heroku 提供的 this 文章并进行了一些更改。 现在,每当我尝试运行命令./gradlew stage 时,一切正常,但是当我尝试使用heroku local web 在本地运行heroku 应用程序时,会产生以下输出。

[WARN] No ENV file found
10:14:18 PM web.1 |  Expanding EmployeeDatabase-0.1.war into /home/ankit/Desktop/Causecode/EmployeeDatabase/build/target/tomcat.5000/webapps/expanded
10:14:18 PM web.1 |  Adding Context  for /home/ankit/Desktop/Causecode/EmployeeDatabase/build/target/tomcat.5000/webapps/expanded
10:14:19 PM web.1 |  Apr 09, 2017 10:14:19 PM org.apache.coyote.AbstractProtocol init
10:14:19 PM web.1 |  INFO: Initializing ProtocolHandler ["http-nio-5000"]
10:14:19 PM web.1 |  Apr 09, 2017 10:14:19 PM org.apache.tomcat.util.net.NioselectorPool getSharedSelector
10:14:19 PM web.1 |  INFO: Using a shared selector for servlet write/read
10:14:19 PM web.1 |  Apr 09, 2017 10:14:19 PM org.apache.catalina.core.StandardService startInternal
10:14:19 PM web.1 |  INFO: Starting service Tomcat
10:14:19 PM web.1 |  Apr 09, 2017 10:14:19 PM org.apache.catalina.core.StandardEngine startInternal
10:14:19 PM web.1 |  INFO: Starting Servlet Engine: Apache Tomcat/8.0.30
10:14:19 PM web.1 |  Apr 09, 2017 10:14:19 PM org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
10:14:19 PM web.1 |  INFO: No global web.xml found
10:14:28 PM web.1 |  Apr 09, 2017 10:14:28 PM org.apache.jasper.servlet.TldScanner scanJars
10:14:28 PM web.1 |  INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
10:14:29 PM web.1 |  Apr 09, 2017 10:14:29 PM org.apache.catalina.core.ApplicationContext log
10:14:29 PM web.1 |  INFO: 2 Spring WebApplicationInitializers detected on classpath
10:14:33 PM web.1 |  Exception in thread "main" org.apache.catalina.LifecycleException: Failed to start component [StandardServer[-1]]
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
10:14:33 PM web.1 |     at org.apache.catalina.startup.Tomcat.start(Tomcat.java:344)
10:14:33 PM web.1 |     at webapp.runner.launch.Main.main(Main.java:261)
10:14:33 PM web.1 |  Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Tomcat]]
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
10:14:33 PM web.1 |     at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:769)
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
10:14:33 PM web.1 |     ... 2 more
10:14:33 PM web.1 |  Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat]]
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
10:14:33 PM web.1 |     at org.apache.catalina.core.StandardService.startInternal(StandardService.java:441)
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
10:14:33 PM web.1 |     ... 4 more
10:14:33 PM web.1 |  Caused by: org.apache.catalina.LifecycleException: A child container failed during start
10:14:33 PM web.1 |     at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:924)
10:14:33 PM web.1 |     at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
10:14:33 PM web.1 |     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
10:14:33 PM web.1 |     ... 6 more
[DONE] Killing all processes with signal  null
10:14:33 PM web.1 Exited with exit code 1

这是我的 Procfile:

web: cd build ; java -Dgrails.env=prod -jar ../build/server/webapp-runner-*.jar --expand-war --port $PORT libs/*.war

这是我的build.gradle

buildscript 
    ext 
        grailsVersion = project.grailsVersion
    
    repositories 
        mavenLocal()
        maven  url "https://repo.grails.org/grails/core" 
    
    dependencies 
        classpath "org.grails:grails-gradle-plugin:$grailsVersion"
        classpath "com.bertramlabs.plugins:asset-pipeline-gradle:2.8.2"
        classpath "org.grails.plugins:hibernate4:5.0.10"
    


plugins 
    id "io.spring.dependency-management" version "0.4.0.RELEASE"


version "0.1"
group "employeedatabase"

apply plugin: "spring-boot"
apply plugin:"eclipse"
apply plugin:"idea"
apply plugin:"war"
apply plugin:"org.grails.grails-web"
apply plugin:"org.grails.grails-gsp"
apply plugin:"asset-pipeline"

ext 
    grailsVersion = project.grailsVersion
    gradleWrapperVersion = project.gradleWrapperVersion


repositories 
    mavenLocal()
    maven  url "https://repo.grails.org/grails/core" 


dependencyManagement 
    imports 
        mavenBom "org.grails:grails-bom:$grailsVersion"
    
    applyMavenExclusions false


dependencies 
    compile "org.springframework.boot:spring-boot-starter-logging"
    compile "org.springframework.boot:spring-boot-autoconfigure"
    compile "org.grails:grails-core"
    compile "org.springframework.boot:spring-boot-starter-actuator"
    compile "org.springframework.boot:spring-boot-starter-tomcat"
    compile "org.grails:grails-dependencies"
    compile "org.grails:grails-web-boot"
    compile "org.grails.plugins:cache"
    compile "org.grails.plugins:scaffolding"
    compile "org.grails.plugins:hibernate4"
    compile "org.hibernate:hibernate-ehcache"
    console "org.grails:grails-console"
    profile "org.grails.profiles:web"
    runtime "com.bertramlabs.plugins:asset-pipeline-grails:2.8.2"

    runtime 'org.postgresql:postgresql:9.4-1201-jdbc4'
    provided "org.springframework.boot:spring-boot-starter-tomcat"

    //runtime "com.h2database:h2"
    runtime "mysql:mysql-connector-java:5.1.29"
    testCompile "org.grails:grails-plugin-testing"
    testCompile "org.grails.plugins:geb"
    testRuntime "org.seleniumhq.selenium:selenium-htmlunit-driver:2.47.1"
    testRuntime "net.sourceforge.htmlunit:htmlunit:2.18"

    compile 'org.eclipse.jetty:jetty-runner:9.2.11.v20150529'
    compile 'com.github.jsimone:webapp-runner:8.0.30.2'

    //adding spring security core plugin
    compile 'org.grails.plugins:spring-security-core:3.0.3'
    //adding oauth plugin
    compile 'org.grails.plugins:oauth:3.0.1'


assets 
    minifyJs = true
    minifyCss = true


task wrapper(type: Wrapper) 
    gradleVersion = gradleWrapperVersion


task stage() 
    dependsOn clean, war

tasks.stage.doLast() 
    delete fileTree(dir: "build/distributions")
    delete fileTree(dir: "build/assetCompile")
    delete fileTree(dir: "build/distributions")
    delete fileTree(dir: "build/libs", exclude: "*.war")

war.mustRunAfter clean

task copyToLib(type: Copy) 
    into "$buildDir/server"
    from(configurations.compile) 
        include "webapp-runner*"
    


stage.dependsOn(copyToLib)

我正在使用 Grails 3.1.10。如果您已在 Heroku 上成功部署了 Grails 3 应用程序,那么一步一步的方法将是无价的。

【问题讨论】:

在 Heroku 上运行应用程序时(添加 stage 任务后)是否遇到相同的异常? @codefinger:是的! 【参考方案1】:

我对 Heroku 没有任何经验,但我在您的 build.gradle 中发现了问题。您提到的在 Heroku 上运行 Grails 3 应用程序的文档链接要求您将两个依赖项添加到您的 build.gradle

runtime 'postgresql:postgresql:8.4-702.jdbc3'
provided "org.springframework.boot:spring-boot-starter-tomcat"

但是依赖关系 org.springframework.boot:spring-boot-starter-tomcat 已经存在于您的 build.gradle 范围内 compile 下,因此存在重复的依赖关系。

org.springframework.boot:spring-boot-starter-tomcat 是 Grails 3 中提供的嵌入式 tomcat,如果要在独立 tomcat 上部署,则必须删除它,否则如果在嵌入式 tomcat 中运行 WAR,将有两个 tomcat 实例,我认为你的错误就是这样。

根据docs:

请注意,默认情况下,Grails 将包含一个可嵌入版本的 WAR 文件中的 Tomcat,如果部署到 不同版本的Tomcat。如果您不打算使用嵌入式 容器,那么您应该更改 Tomcat 依赖项的范围 在部署到您的生产容器之前提供 build.gradle:

provided "org.springframework.boot:spring-boot-starter-tomcat"

所以考虑删除compile "org.springframework.boot:spring-boot-starter-tomcat"这一行。

【讨论】:

以上是关于无法在 Heroku 上部署我的 Grails 3 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

在 Heroku 上使用 ActionCable 部署 Rails5 beta3 应用程序时 Redis 密码无效

尝试在 Heroku 上部署,没有工作,现在本地服务器无法工作

由于静态错误,无法在 Heroku 上部署 Django [重复]

Heroku 部署无法看到 Angular 组件

将 rails 应用程序从 3.2.3 迁移到 rails 4.0.0.rc2 后无法在 Heroku 上部署

找不到静态文件 - 在 Heroku 上部署 Django