Deployment 我可以从Procfile给Maven打电话吗?
我正在将Heroku作为一个平台进行研究,并尝试在其上运行一个基本的JavaWebApp。webapp已经使用Maven构建和运行(使用Tomcat和cargo-Maven插件),因此我认为这应该是一件轻而易举的事情,因为Heroku使用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
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
,因此命令失败
是否可以从HerokuProcfile
调用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