【问题标题】:Correct way to deploy WAR files in docker image在 docker 镜像中部署 WAR 文件的正确方法
【发布时间】:2015-05-15 05:59:30
【问题描述】:

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

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

FROM jetty:9.2.10
MAINTAINER Me "me@me.com"
ADD ./target/*.war /var/lib/jetty/webapps/ROOT.war

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

FROM jetty:9.2.10
MAINTAINER Me "me@me.com"
ADD ./target/app-0.1.0.BUILD-SNAPSHOT /var/lib/jetty/webapps/ROOT

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

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

【问题讨论】:

    标签: java maven jetty docker dockerfile


    【解决方案1】:

    您实际上应该始终部署爆炸的 .war。

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

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

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

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

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

    1. 它使容器版本之间的差异更小,因此您的上传时间更短。
    2. 这意味着,在动态扩展以满足应用程序需求时,您的新容器实例无需解压缩 .war 文件即可开始响应请求。

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

    【讨论】:

      【解决方案2】:

      这就是我的做法:

      FROM tomcat:8.0
      MAINTAINER David Ford <dford@smart-soft.com>
      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
      

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

      【讨论】:

        【解决方案3】:

        如果您像我一样在这里偶然发现,寻找如何简单地将 WAR 部署在容器中(使用 Apache Tomcat),而不关心您是否有 Dockerfile

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

        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
        

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

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

        我还发现,在通过 IntelliJ 的 Docker Plugin 工作时,很容易将其适应 Docker 插件。请务必输入完整路径。

        【讨论】:

          【解决方案4】:

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

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

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

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

          我的 Dockerfile 非常简单,是我的 Spring Boot 应用程序所需要的全部内容:

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

          您可以执行类似的操作并使用 -v 选项等将卷映射到您的应用程序、环境设置等。顺便说一句,this image 可在 Docker Hub 上使用。

          【讨论】:

          • 也许我应该用 Jenkins 在服务器上构建和打包项目,然后 20MB 将是即时的,从我的 Macbook 上它不是即时的,20MB 在 8 兆位互联网上永远需要。
          • 我认为这将是一个非常好的方法。让 Jenkins 不仅是您的 CI 服务器,而且是您的自动化服务器:也可以使用它来构建、测试和打包您的系统。
          【解决方案5】:

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

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

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

          【讨论】:

            猜你喜欢
            • 2020-08-19
            • 1970-01-01
            • 2015-04-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-10-29
            相关资源
            最近更新 更多