使用Docker开发Java EE应用程序

我将增加300点作为赏金

我最近开始仔细研究Docker,以及如何使用它来更快地获得团队的新成员,并使用开发环境运行,并将新版本的软件发布到生产环境中。

我有一些关于如何以及在什么阶段将Java EE应用程序添加到容器的问题。 正如我所看到的那样,有多种方式可以做到这一点。

这是Docker之前的典型工作stream程(在我的团队中):

  1. 开发者编写代码
  2. 开发人员使用产生WAR的Maven构build代码
  3. 开发人员在JBosspipe理控制台/或Maven插件中上传WAR

现在Docker出现之后,我对我是否应该创build需要的映像并对其进行configuration有点困惑,以至于在运行JBoss Wildfly容器时所做的所有事情是通过Web上的pipe理控制台部署应用程序。 或者我应该每次在Maven中构build应用程序时创build一个新的容器,并将其ADD到Dockerfile中的ADD命令中,然后运行该容器,而不需要在启动后部署它?

在生产中,我猜最后的方法是什么它的优点? 纠正我,如果我错了。 但是在发展中应该怎么做呢? 还有其他工作stream程吗?

我已经广泛地使用了Glassfish的Docker,现在已经很长一段时间了,并且在这里写了一个关于这个主题的博客。

它是JavaEE开发的一个很好的工具。

对于您的制作图片,我更愿意将所有内容捆绑在一起,构build静态基础图像,并在新的WAR中进行分层。 我喜欢使用CI服务器来完成这项工作,并为生产分支机构configurationCIconfiguration,这将在发布版本中获取基础层,然后发布工件。 通常情况下,我们手动部署到生产环境中,但是如果您真的想要使用它,甚至可以将CI服务器部署到生产环境中,并使用代理服务器来自动执行,以确保新的会话得到更新的版本。

在开发过程中,我喜欢在签入代码之前采取相同的方法,在本地运行任何依赖容器(例如Arquillian集成testing)的代码。 这使得环境尽可能地接近生产,我认为在testing方面非常重要。 这是我反对像使用embedded式容器进行testing但部署到非embedded式容器的一个重要原因。 我已经看到很多情况下,testing将通过embedded式环境,并在生产/非embedded式环境中失败。

在开发/部署/手动testing周期中,在提交代码之前,我认为部署到容器(这是基本映像的一部分)的方法在开发速度方面更具成本效益。 每次都在WAR中build立一个循环与build立。 如果您的开发环境使用像JRebel或XRebel这样的工具,那么您可以热部署代码,只需刷新浏览器即可查看更改,这也是一个更好的方法。

使用最新版本的Docker,您可以轻松实现Docker链接,Docker卷和Docker Compose 。 有关Docker站点的这些工具的更多信息。

回到您的工作stream程中,如上所述:对于任何典型的Java EE应用程序,都需要应用程序服务器和数据库服务器。 既然你没有在你的文章中提到如何设置数据库,我会假设你的开发环境将为每个开发人员分离数据库服务器。

把所有这些假设,我可以build议以下工作stream程:

  • 从官方图像构build基本的Wildfly应用程序服务器。 你可以通过“docker pull”命令来实现
  • 运行基本应用程序服务器:

docker运行-d -it -p 8080:8080 -p 9990:9990 – 名称baseWildfly jboss / wildfly

应用程序服务器现在正在运行,您需要将其configuration为连接到数据库服务器,还可以configuration数据源设置和其他configuration(如果需要)以启动Java EE应用程序。 为此,您需要login到Jboss容器的bashterminal:

docker exec -i -t baseWildfly / bin / bash /

你现在在集装箱docker。 您可以像在任何Linux环境中一样configuration应用程序服务器。

您可以通过手动将WAR文件部署到Wildfly来testingconfiguration。 这可以通过pipe理控制台或maven插件或ADD命令轻松完成。 我通常使用pipe理控制台来做这件事,只是为了快速testing。 validationconfiguration是否有效时,可以删除WAR文件并创build容器的快照:

docker提交 – 改变“添加基地设置和configuration”baseWildfly yourRepository:标记

您现在可以将创build的图像推送到您的私人存储库,并与开发人员团队共享。 他们现在可以拉图像并运行应用程序服务器来立即部署。

我们不希望使用pipe理控制台为每个Maven构build部署WAR文件,因为这太麻烦了,所以下一个任务是使用Docker Volume自动化它。

假设您已将Mavenconfiguration为将WAR文件构build为“../ your_project / deployments /”,您可以将其链接到Jboss容器的部署目录,如下所示:

docker run -d -p 8080:8080 -v ../your_project/deployments:/opt/jboss/wildfly/standalone/deployments

现在,每次使用Maven重build应用程序时,应用程序服务器都将扫描更改并重新部署WAR文件。

为每个开发人员分开数据库服务器也是一个问题,因为他们必须自己在容器中configuration它,因为它们可能有不同的设置(例如数据库的URL,用户名,密码等等)。 所以,最终docker化是一件好事。

假设你使用Postgres作为你的数据库服务器,你可以从postgres官方仓库中取出它。 准备好映像后,可以运行数据库服务器:

docker运行-d -p 5432:5432 -t –name postgresDB postgres

或者使用链接的“data”目录运行数据库服务器:

docker运行-d -p 5432:5432 -v ../your_postgres/data:/var/lib/postgresql -t –name postgresDB postgres

第一个命令会将数据保存在容器中,而后一个命令会将数据保存在主机env中。

现在,您可以将数据库容器与Wildfly链接起来:

docker运行-d -p 8080:8080 – 链接postgresDB:数据库-t baseWildfly

以下是链接的输出: 在这里输入图像说明

现在,开发者团队中的所有成员都可以拥有相同的环境,并且可以使用最less的设置开始编码。

生产环境中可以使用相同的基本映像,因此,无论何时要发布新版本,只需将WAR文件复制到主机的“your_deployment”文件夹即可。

dockerizing应用程序服务器和db服务器的好处是您可以在将来轻松地进行群集以扩展或应用高可用性。

你可能想看看rhuss / docker-maven-plugin 。 它允许使用docker作为部署单元的无缝集成:

  • 使用标准的Maven组件描述符来构builddocker:build图像,所以你生成的WAR文件或者你的Microservice可以很容易的添加到Docker镜像中。
  • 您可以使用docker:push来推送创build的图像
  • 使用docker:startdocker:stop在unit testing期间使用你的镜像。

这个插件附带了一个全面的文档,如果有任何未解决的问题,请打开一个问题。

正如你可能已经注意到的,我是这个插件的作者;-)。 坦率地说,还有其他的docker-maven-plugins,它们都有一个稍微不同的重点。 对于一个简单的检查,你可以看看枪战docker maven ,它提供了四个最活跃的maven-docker-plugins的样本configuration。

然后工作stream程将工件边界从WAR / EAR文件转换为Docker镜像。 mvn docker:push在持续交付stream水线中使用的各种testing阶段, mvn docker:push将它们从Dockerregistry中移到Dockerregistry。

您通常会使用Docker部署任何东西的方式是在平台基础映像的顶部生成一个新映像。 这样你就可以遵循Docker依赖关系捆绑的理念。

就Maven而言,您可以生成一个tarball程序集(假设它叫做jars.tar ),然后在Dockerfile中调用ADD jars.tar /app/lib 。 你也可以实现一个生成Dockerfile的Maven插件。

这是Docker今天最为理智的方法,其他方法(如FROM scratch构build映像)并不适用于Java应用程序。

另请参阅Docker / CoreOS上的Java JVM 。

关于用Arun Gupta与Docker搭buildJRebel的博客文章在这里可能会很方便: http ://blog.arungupta.me/configure-jrebel-docker-containers/

我已经尝试了一个使用docker来运行我的应用程序的相似场景。 在我的情况下,我想开始与tomcat运行战争的docker。 然后在Maven的集成testing阶段,在Docker上启动黄瓜/ phantomjs集成testing。 示例实现logging在https://github.com/abroer/cucumber-integration-test 。 你可以扩展这个例子,在testing成功时将docker镜像推送到你的私有仓库。 推送的图像可以用于从开发到生产的任何环境。

对于我目前的部署过程,我使用glassfish和这个技巧,这非常好。

 <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>${plugin.exec.version}</version> <executions> <execution> <id>docker</id> <phase>package</phase> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <executable>docker</executable> <arguments> <argument>cp</argument> <argument>${project.build.directory}/${project.build.finalName}</argument> <argument>glassfish:/glassfish4/glassfish/domains/domain1/autodeploy</argument> </arguments> </configuration> </plugin> 

一旦你运行:mvn clean package,容器会启动并开始部署最新的战争。