Java 在 docker 镜像中部署 WAR 文件的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30252532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 09:23:05  来源:igfitidea点击:

Correct way to deploy WAR files in docker image

javamavenjettydockerdockerfile

提问by Jan Vladimir Mostert

What is the docker way to deploy java projects in a docker container?

在docker容器中部署java项目的docker方式是什么?

Do I copy the war into webapps:

我是否将战争复制到 webapps 中:

FROM jetty:9.2.10
MAINTAINER Me "[email protected]"
ADD ./target/*.war /var/lib/jetty/webapps/ROOT.war

or do I take the exploded war file:

还是我拿爆炸的战争文件:

FROM jetty:9.2.10
MAINTAINER Me "[email protected]"
ADD ./target/app-0.1.0.BUILD-SNAPSHOT /var/lib/jetty/webapps/ROOT

Normally one would deploy the sealed war file if it was a normal container, but with docker, that means pushing a 10-20MB file every time you make a small change whereas adding the exploded war would only push the difference - the .class file that has changed.

通常,如果它是一个普通容器,就会部署密封的战争文件,但是对于 docker,这意味着每次进行小的更改时都会推送一个 10-20MB 的文件,而添加分解的战争只会推送差异 - .class 文件已经改变。

Are there any downsides to deploying the exploded war instead of the war file?

部署爆炸战争而不是战争文件有什么缺点吗?

采纳答案by objectuser

I wonder how you're using your images. Adding a 20MB file while building an image should almost be instant. Mayb you somehow building images during deployment, like AWS does when you give it a Dockerfile.

我想知道你如何使用你的图像。在构建图像时添加 20MB 文件应该几乎是即时的。也许你在部署过程中以某种方式构建了镜像,就像 AWS 在你给它一个 Dockerfile 时所做的那样。

In any case, I think it depends on how you're deploying. If you're moving the images around yourself, I don't see a lot of difference between ADDing a .war file and an exploded WAR directory. I would say do what's convenient for you. However, if you sometimes run the app from Docker and sometimes from a .war (which might miss some of the point of Docker), you might as well use the .war all the time.

无论如何,我认为这取决于您的部署方式。如果您在自己周围移动图像,我认为添加 .war 文件和分解的 WAR 目录之间没有太大区别。我会说做你方便的事情。但是,如果您有时从 Docker 运行应用程序,有时从 .war 运行应用程序(这可能会错过 Docker 的某些要点),那么您最好一直使用 .war。

If you're deploying to something like AWS Elastic Beanstalk (something that pulls the image from a repository), which wants either a Dockerfile or a Dockerrun.aws.json file, then separating the image from what you actually deploy makes some sense (or it has made sense to me so far). This allows the container to stay the same, while updating your app can be just copying a .jar/.war file to the right location (which also might miss part of the point of Docker ;).

如果您要部署到像 AWS Elastic Beanstalk(从存储库中提取映像的东西)这样的东西,它需要 Dockerfile 或 Dockerrun.aws.json 文件,那么将映像与实际部署的内容分开是有意义的(或到目前为止,这对我来说很有意义)。这允许容器保持不变,而更新您的应用程序可以只是将 .jar/.war 文件复制到正确的位置(这也可能会错过 Docker 的部分要点;)。

What I've been doing is creating a base image on Docker Hub and then using the Dockerrun.aws.json file to map in my app. That way, AWS does not need to build my image, just pull it. That's much faster and less costly ($). But it does separate my app from the image, which might complicate deployment in some circumstances. However, because my image is so stable, I generally just bundle a .jar file, a Dockerrun.aws.json file and a shell script into a .zip and upload it to AWS. Pretty easy I think.

我一直在做的是在 Docker Hub 上创建一个基本映像,然后使用 Dockerrun.aws.json 文件在我的应用程序中进行映射。这样,AWS 不需要构建我的映像,只需拉取它即可。这更快,成本更低($)。但它确实将我的应用程序与图像分开,这在某些情况下可能会使部署复杂化。但是,因为我的镜像非常稳定,所以我通常只将一个 .jar 文件、一个 Dockerrun.aws.json 文件和一个 shell 脚本捆绑到一个 .zip 中并将其上传到 AWS。我觉得很容易。

My Dockerfile is pretty simple and really all I need for my Spring Boot app:

我的 Dockerfile 非常简单,真的是我的 Spring Boot 应用程序所需要的:

FROM java:8
VOLUME /tmp
VOLUME /app
EXPOSE 8080
ENTRYPOINT ["sh","/app/app.sh"]

You could do something similar and use the -v option, etc., to map volumes to your app, it's environment settings, etc. BTW, this imageis available on Docker Hub.

你可以做一些类似的事情并使用 -v 选项等,将卷映射到你的应用程序,它的环境设置等。顺便说一句,这个图像在 Docker Hub 上可用。

回答by Yogesh_D

You can try this: Copy the war file into the container using COPY Copy the jetty runner jar into the container using COPY and then use the CMD to run it like this ["java -jar /path/to/jetty-runner.jar /path/to/app.war"]

你可以试试这个: 使用 COPY 将 war 文件复制到容器中 使用 COPY 将 jetty runner jar 复制到容器中,然后使用 CMD 像这样运行它 ["java -jar /path/to/jetty-runner.jar /路径/到/app.war"]

http://www.eclipse.org/jetty/documentation/current/runner.html

http://www.eclipse.org/jetty/documentation/current/runner.html

NOTE: you will need to have java installed in the container.

注意:您需要在容器中安装 java。

回答by Ryan Kimber

You should actually ALWAYS deploy the exploded .war.

实际上,您应该始终部署分解的 .war。

There are two elements of speed to think about here:

这里有两个速度要素需要考虑:

  1. How fast is it to be able to push up your image to a container repository?

    and

  2. How quickly can a new instance of my container start serving requests? (important in an elastic-scaling environment)

  1. 将镜像推送到容器存储库的速度有多快?

  2. 我的容器的新实例可以多快开始处理请求?(在弹性扩展环境中很重要)

The answer to both is the same: You are better off exploding the .war file when creating your container and NOT copying the .war file to it.

两者的答案是一样的:最好在创建容器时分解 .war 文件,而不是将 .war 文件复制到其中。

This has the following two very positive effects:

这有以下两个非常积极的影响:

  1. It makes the differences between container versions much smaller, and so your upload time is less.
  2. It means that, when dynamically scaling to meet application demand, your new container instances don't have to unzip your .war file before they can start responding to requests.
  1. 它使容器版本之间的差异更小,因此您的上传时间更少。
  2. 这意味着,当动态扩展以满足应用程序需求时,您的新容器实例在开始响应请求之前不必解压缩您的 .war 文件。

For those of us burdened by slow-upload connections, it's also a great idea to use a CI server or even a cloud-hosted VM to build and push your docker images to dockerhub or another container registry. That way you can take advantage of gigabit-scale upload speeds.

对于我们这些受缓慢上传连接负担的人来说,使用 CI 服务器甚至云托管的 VM 来构建您的 docker 镜像并将其推送到 dockerhub 或其他容器注册表也是一个好主意。这样您就可以利用千兆级的上传速度。

回答by Dave Ford

This is how I do it:

这就是我的做法:

FROM tomcat:8.0
MAINTAINER David Ford <[email protected]>
ENV DB_HOST mySqlServer
ENV DB_USER joeBlow
ENV DB_PASSWORD bla bla bla
EXPOSE 8080
RUN rm -fr /usr/local/tomcat/webapps/ROOT
COPY target/webapp /usr/local/tomcat/webapps/ROOT

On my todo list: separate out the WEB_INF/lib dir into its own container.

在我的待办事项列表中:将 WEB_INF/lib 目录分离到它自己的容器中。

回答by NonCreature0714

If you stumbled here, like I did, looking for how to simply get a WAR deployed in a container (using Apache Tomcat), and didn't care whether or not you have a Dockerfile.

如果您像我一样在这里偶然发现如何简单地在容器中部署 WAR(使用Apache Tomcat),并且不在乎您是否有Dockerfile.

A simple, elegant solution.

一个简单、优雅的解决方案。

docker run \
-d \ # Detached mode, swap for -it if we want interactive.
-p 8080:8080  \
-v ${absolute_path_your_project_dir}/${MY_WAR}.war:/usr/local/tomcat/webapps/app.war \
tomcat:latest

Then navigate to http://localhost:8080/app/.

然后导航到http://localhost:8080/app/

If that link doesn't work for you, be sure to change ...8080/app/in the URLto whatever matches the .warname you gave in /usr/local/tomcat/webapps/app.war.

如果该链接对您不起作用,请确保...8080/app/将 URL更改为与.war您在中提供的名称匹配的任何内容/usr/local/tomcat/webapps/app.war

I also found that, while working through IntelliJ's Docker Plugin, it's easy to adapt this to Docker Plugins. Just be sure to put in your full path.

我还发现,在通过 IntelliJ 的Docker Plugin 工作时,很容易将其适应Docker Plugin。只要确保输入完整路径即可。