Deployment 我可以从Procfile给Maven打电话吗?

Deployment 我可以从Procfile给Maven打电话吗?,deployment,maven,heroku,Deployment,Maven,Heroku,我正在将Heroku作为一个平台进行研究,并尝试在其上运行一个基本的JavaWebApp。webapp已经使用Maven构建和运行(使用Tomcat和cargo-Maven插件),因此我认为这应该是一件轻而易举的事情,因为Heroku使用Maven来管理其安装/部署任务 但事实并非如此,因为我无法让它真正启动。我的Procfile中包含以下内容: web: sh ./startServer-heroku.sh 而startServer heroku.sh只是: mvn clean instal

我正在将Heroku作为一个平台进行研究,并尝试在其上运行一个基本的JavaWebApp。webapp已经使用Maven构建和运行(使用Tomcat和cargo-Maven插件),因此我认为这应该是一件轻而易举的事情,因为Heroku使用Maven来管理其安装/部署任务

但事实并非如此,因为我无法让它真正启动。我的
Procfile
中包含以下内容:

web: sh ./startServer-heroku.sh
startServer heroku.sh
只是:

mvn clean install cargo:start -Dcargo.maven.wait=true
当我使用
foreman start
命令在本地进行测试时,这很好,如Heroku教程文档中所述。但当我在实际的Heroku服务器上尝试时,会收到以下日志消息:

2011-11-09T02:30:27+00:00 heroku[web.1]: State changed from created to starting 
2011-11-09T02:30:27+00:00 heroku[slugc]: Slug compilation finished 
2011-11-09T02:30:33+00:00 heroku[web.1]: Starting process with command `sh ./startServer-heroku.sh` 
2011-11-09T02:30:33+00:00 app[web.1]: ./startServer-heroku.sh: 1: mvn: not found 
2011-11-09T02:30:33+00:00 heroku[web.1]: Process exited 
2011-11-09T02:30:34+00:00 heroku[web.1]: State changed from starting to crashed
似乎在系统的
路径上找不到
mvn
,因此命令失败


是否可以从Heroku
Procfile
调用
mvn
?是否有任何地方可以从
Procfile
中获得或无法获得命令的最终列表

Maven不在部署到dynos的slug中。它只在编译时可用。处理此问题的一个选项是使用
appassembler maven插件
jar
打包来生成启动脚本:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>appassembler-maven-plugin</artifactId>
            <version>1.1.1</version>
            <configuration>
                <assembleDirectory>target</assembleDirectory> 
                <programs>
                    <program>
                        <mainClass>foo.Main</mainClass>
                        <name>webapp</name>
                    </program>
                </programs>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>assemble</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
另一个选项是
maven依赖插件
war
打包:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.mortbay.jetty</groupId>
                                <artifactId>jetty-runner</artifactId>
                                <version>7.5.3.v20111011</version>
                                <destFileName>jetty-runner.jar</destFileName>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

James的回答为Jetty在Heroku上的工作提供了很好的指导,他的评论还包括一个链接,指向使用嵌入式Tomcat的良好参考。但也可以在Heroku上运行标准、独立版本的Tomcat。以下是我如何让它工作的:

首先,将POM设置为在构建过程中安装和配置Tomcat,并将应用程序部署到已安装的Tomcat实例:

        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <configuration>
                <container>
                    <containerId>tomcat6x</containerId>
                    <zipUrlInstaller>
                        <url>http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip</url>
                    </zipUrlInstaller>
                    <dependencies>
                        <dependency>
                            <groupId>javax.activation</groupId>
                            <artifactId>activation</artifactId>
                        </dependency>
                        <dependency>
                            <groupId>javax.mail</groupId>
                            <artifactId>mail</artifactId>
                        </dependency>
                    </dependencies>
                </container>
                <configuration>
                    <type>standalone</type>
                    <deployables>
                        <deployable>
                            <groupId>com.yourcompany.name</groupId>
                            <artifactId>yourArtifact</artifactId>
                            <type>war</type>
                            <properties>
                                <context>ROOT</context>
                            </properties>
                        </deployable>
                    </deployables>
                </configuration>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>install</goal>
                        <goal>configure</goal>
                        <goal>deploy</goal>
                        <goal>package</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
…这是必要的,因为您的Heroku应用程序只允许绑定到单个端口(每次创建新实例时都会更改,并且在环境变量
$port
中指定)。尝试绑定到任何其他端口将导致应用程序崩溃。由于端口是动态的,因此必须通过
http.port
系统属性将其传递到
server.xml
,但稍后我们将讨论这个问题

同时,还要创建一个将与Heroku一起使用的
persistence.xml
文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="quiz_devel">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.archive.autodetection" value="class"/>
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
      <property name="hibernate.show.sql" value="true"/>
      <property name="hibernate.c3p0.acquire_increment" value="1"/> 
      <property name="hibernate.c3p0.idle_test_period" value="10"/>
      <property name="hibernate.c3p0.max_size" value="20"/>
      <property name="hibernate.c3p0.max_statements" value="40"/>
      <property name="hibernate.c3p0.min_size" value="1"/> 
      <property name="hibernate.c3p0.timeout" value="30"/>
    </properties>
  </persistence-unit>
</persistence>
这是在做一些事情:

  • 它通过将
    CATALINE_BASE
    设置为指向正确的位置,告诉Tomcat使用作为构建一部分打包的配置和部署工件
  • 它用特定于heroku的变体覆盖默认的
    server.xml
    persistence.xml
    文件
  • 它将Tomcat实例中作为构建的一部分安装的所有启动脚本标记为可执行脚本
  • 它根据Heroku平台提供的环境变量为
    http.port
    hibernate.connection.url
    指定值
  • 最后,它运行Tomcat。请注意,不能使用
    startup.sh
    执行此操作,因为
    startup.sh
    将在新进程中启动Tomcat,然后终止。Heroku不明白这一点,认为
    startup.sh
    的终止就是Tomcat进程的终止
  • 最后,最后一步是设置
    Procfile
    以调用启动脚本,大致如下:

    web: sh startServer-heroku.sh
    

    通过这种方法,您可以拥有一个与Heroku兼容的项目,同时仍然保留其作为标准Java webapp独立运行的能力。

    是的,您可以从proc文件调用maven

    为此,您需要通过对java构建包中的“compile”脚本进行一个小的修改,将maven包括在slug中,如下所述:

    例如,如果您想让maven在应用程序运行时可用,只需将其从缓存目录复制到构建目录,方法是向编译脚本添加以下行:

    我在下载maven之后,在更改为BUILD_DIR之前

    然后可以在Procfile中调用.maven/bin/mvn


    如果您正在构建一个可以从java或servlet容器中运行的工件(war/jar),那么您可能应该按照其他答案做一些事情,但是如果您确实需要运行maven,那么这就是方法。

    谢谢,这很有意义,尽管您的示例使用的是Jetty。你知道有没有可能用Tomcat做一件类似的事情吗?Tomcat没有jetty runner的等价物,但是你仍然可以用Tomcat以几种方式进行部署。一种是使用嵌入式Tomcat。查看刚刚发布的这篇文章:看一看,它自动化了Heroku的整个部署过程。也许对你有帮助。
    <?xml version='1.0' encoding='utf-8'?> 
    <Server port="-1"> 
        <Listener className="org.apache.catalina.core.JasperListener" /> 
        <Service name="Catalina"> 
            <Connector port="${http.port}" protocol="HTTP/1.1" connectionTimeout="20000"/> 
            <Engine name="Catalina" defaultHost="localhost"> 
                <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"/> 
            </Engine> 
        </Service> 
    </Server>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
      <persistence-unit name="quiz_devel">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
          <property name="hibernate.archive.autodetection" value="class"/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
          <property name="hibernate.hbm2ddl.auto" value="update"/>
          <property name="hibernate.show.sql" value="true"/>
          <property name="hibernate.c3p0.acquire_increment" value="1"/> 
          <property name="hibernate.c3p0.idle_test_period" value="10"/>
          <property name="hibernate.c3p0.max_size" value="20"/>
          <property name="hibernate.c3p0.max_statements" value="40"/>
          <property name="hibernate.c3p0.min_size" value="1"/> 
          <property name="hibernate.c3p0.timeout" value="30"/>
        </properties>
      </persistence-unit>
    </persistence>
    
    #point to the correct configuration and webapp
    CATALINA_BASE=`pwd`/target/cargo/configurations/tomcat6x
    export CATALINA_BASE
    
    #copy over the Heroku config files
    cp ./server-heroku.xml ./target/cargo/configurations/tomcat6x/conf/server.xml
    cp ./persistence-heroku.xml ./target/cargo/configurations/tomcat6x/webapps/ROOT/WEB-INF/classes/META-INF/persistence.xml
    
    #make the Tomcat scripts executable
    chmod a+x ./target/cargo/installs/apache-tomcat-6.0.18/apache-tomcat-6.0.18/bin/*.sh
    
    #set the correct port and database settings
    JAVA_OPTS="$JAVA_OPTS -Dhttp.port=$PORT -Dhibernate.connection.url=$DATABASE_URL"
    export JAVA_OPTS
    
    #start Tomcat
    ./target/cargo/installs/apache-tomcat-6.0.18/apache-tomcat-6.0.18/bin/catalina.sh run
    
    web: sh startServer-heroku.sh
    
    for DIR in ".m2" ".maven" ; do
     cp -r $CACHE_DIR/$DIR $BUILD_DIR/$DIR
    done