Java docker文件。构建并测试或只运行jar文件?

时间:2017-07-27 14:30:50

标签: java maven docker gradle continuous-integration

我在CI管道中想到这一点,我应该首先构建并测试我的应用程序,结果应该是一个docker镜像。

我想知道使用构建环境构建构建服务器然后运行测试是否更常见。也许使用构建脚本。最后,只需将jar文件添加到使用COPY生成的Docker容器中,然后使用Entrypoint java -jar .jar。因此,保持Dockerfile非常小,并在容器外进行测试和构建。

有点像这样:

FROM openjdk:8-jre-alpine
CMD java ${JAVA_OPTS} -jar *.jar
COPY build/libs/*.jar .

或者,如果我应该将所有源代码添加到容器中,构建它然后在容器内运行测试,然后使用Entrypoint(如前所述)运行生成的jar文件?所以保持Dockerfile中的所有内容?也许做一些清理,删除源代码

我猜这不是Java,同样的问题适用于所有语言

3 个答案:

答案 0 :(得分:2)

您可以使用JDK以及为此目的所需的所有工具在所谓的构建docker映像中构建和测试应用程序。当你完成并且开心时,你将jar / war作为工件提取到你的CI / CD管道中,然后,当你考虑生产就绪时,你构建一个生产docker镜像并将工件放在里面,你只有一个JRE / Tomcat(无论你需要什么生产) - 没有开发工具,没有编译工具 - 尽可能小巧,简洁。

所以你基本上每个应用程序至少有2个图像,一个用于构建它,另一个用于在生产中运行它。混合两者是非常糟糕的做法,迟早会导致问题。

在主机上构建更糟糕,因为你没有以这种方式使用干净的环境,这或多或少是docker的关键收益之一 - 你无法轻松地在本地重现构建。

答案 1 :(得分:2)

优化容器构建

历史上,为了创建一个不包含源代码的docker镜像(以及用于创建二进制文件的软件),人们不得不两次运行Docker。例如参见

现在,Docker支持新的多阶段构建功能:

这使Docker能够构建一个包含构建工具的图像的容器,但输出的图像只包含运行时依赖项。以下示例演示了此概念,请注意如何从第一个构建阶段的目标目录复制jar

FROM maven:3.3-jdk-8-onbuild 

FROM java:8
COPY --from=0 /usr/src/app/target/demo-1.0-SNAPSHOT.jar /opt/demo.jar
CMD ["java","-jar","/opt/demo.jar"]

结果图像不包含maven,只包含java和构建的jar。

测试

假设我们不讨论单元测试(可以在本地运行),集成测试需要首先部署代码。在这种情况下,答案很大程度上取决于您如何部署容器化Java应用程序。

例如,如果您正在使用Kubernetes或Openshift,则可以使用Fabric8 plugin部署代码,然后在Maven中运行测试阶段。

答案 2 :(得分:0)

为解决此问题,我借鉴了计算机科学的SoC(关注分离)设计原理,并决定采用两种docker image方法:一种用于构建/测试应用程序,另一种用于运行应用程序。将流程分开的另一个好处是减少了意外行为的发生,这将简化维护和回归测试。