简体   繁体   English

Java 和 Docker 的缓慢开发工作流程/反馈循环:我是否需要在每次更改后重建 JAR 和图像?

[英]Slow development workflow/feedback loop for Java with Docker: do I need to rebuild the JAR and image after every change?

I am trying to dockerize a Java app, but currently my development feedback loop is much slower when working with Docker compared to when I am working without Docker. With Docker, I have to rebuild my jar and the image after every change (see more detailed workflow below), causing a slow feedback loop.我正在尝试对 Java 应用程序进行 docker 化,但与我在没有Docker 的情况下工作相比,目前我的开发反馈循环在使用Docker 时要慢得多。使用Docker,我必须在每次更改后重建我的 jar 和图像(查看更多详细信息下面的工作流程),导致缓慢的反馈循环。 What do Java devs in the Docker world do to avoid this? Docker 世界中的 Java 开发人员如何避免这种情况?

Dockerfile (for reference): Dockerfile(参考):

FROM openjdk:8    
WORKDIR /usr/src/app  
COPY /target/my-project.jar .  
CMD ["java",  "-jar",  "my-project.jar"]

Java development workflow with Docker (feedback takes 3-5 minutes after each change): JavaDocker 的开发工作流程(每次更改后反馈需要 3-5 分钟):

  1. Make a change locally to my Java codebase.在本地对我的 Java 代码库进行更改。
  2. However small the change in #1 is, I need to rebuild my jar (using maven package);无论#1 中的变化多么小,我都需要重建我的 jar(使用 maven 包); this takes 3-4 minutes for my codebase.我的代码库需要 3-4 分钟。
  3. Rebuild image.重建图像。
  4. Run container and see if change went through.运行容器并查看更改是否通过。

Java development workflow without Docker (feedback takes seconds after each change): JavaDocker的开发流程(每次修改后秒反馈):

  1. Make a change locally to my Java codebase.在本地对我的 Java 代码库进行更改。
  2. Click run on my Intellij run configuration, which runs my main method immediately, and see if changes went through.在我的 Intellij 运行配置上单击“运行”,它会立即运行我的主要方法,并查看更改是否通过。

From what I can tell, my local development feedback loop (without Docker) is so much faster because Intellij is able to cache all bytecode (ie, the class files in the "target/" directory), rebuilds the class file(s) for only the class(es) that changed, keeps track of my classpath, and runs my main method.据我所知,我的本地开发反馈循环(没有 Docker)快得多,因为 Intellij 能够缓存所有字节码(即“target/”目录中的 class 文件),重建 class 文件只有改变的类,跟踪我的类路径,并运行我的主要方法。 It doesn't need to rebuild the entire jar, and therefore is much, much faster.它不需要重建整个 jar,因此速度快得多。 I'm not sure how to replicate this in Docker.我不确定如何在 Docker 中复制它。

UPDATE/ANSWER更新/回答

I solved this problem with the following approach:我用以下方法解决了这个问题:

  1. Bind-mounted my project's target folder to /usr/src/app/target in the container and now just call the main class in my Dockerfile CMD, not ever bringing the JAR into the container.将我的项目的目标文件夹绑定到容器中的 /usr/src/app/target,现在只需在我的 Dockerfile CMD 中调用主要的 class,永远不要将 JAR 放入容器中。 Thanks to @kutschkem.感谢@kutschkem。

  2. Added maven-dependency-plugin to my pom.xml, so that all of my external jar dependencies could be saved to one folder (/usr/src/app/target/dependency-jars/), which I could then add to my classpath in one fell swoop in my Dockerfile CMD below.将 maven-dependency-plugin 添加到我的 pom.xml,这样我所有的外部 jar 依赖项都可以保存到一个文件夹 (/usr/src/app/target/dependency-jars/),然后我可以将其添加到我的类路径一举在我的Dockerfile CMD下面。 Got the idea from this article: https://medium.com/holisticon-consultants/dont-build-fat-jars-for-docker-applications-6252a5571248 .从这篇文章中得到了这个想法: https://medium.com/holisticon-consultants/dont-build-fat-jars-for-docker-applications-6252a5571248

New Dockerfile:新 Dockerfile:

FROM openjdk:8    
WORKDIR /usr/src/app/target
CMD ["java",  "-cp", "/usr/src/app/target/classes:/usr/src/app/target/dependency-jars/*",  "com.me.MainClass"]

There are two things that can be improved here:这里有两点可以改进:

1) Don't copy the jar file to the image, mount the folder in the container as a volume with -v 1)不要将jar文件复制到镜像中,使用-v将容器中的文件夹挂载为卷

2) If building the jar is an issue, then don't, Prepare a java invocation that includes the necessary classpath. 2) 如果构建 jar 是一个问题,那么不要,准备一个包含必要类路径的 java 调用。 and calls the main class. No need for a jar.并呼叫主要 class。不需要罐子。

Of course this is for development, but functionally there shouldn't be much difference.当然这是为了开发,但功能上应该没有太大区别。 Also, is there a good reason to test the classes inside the docker container?另外,是否有充分的理由测试 docker 容器内的类? If I were to do it, I would seperate the development of the Java classes and the Docker image, and use the workflow you described WITHOUT docker to test my Java code, and only once I am satisfied turn to the image development.如果我要这样做,我会分开开发 Java 类和 Docker 图像,并使用您描述的工作流程(不带 docker)来测试我的 Java 代码,只有当我满意时才转向图像开发。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM