【问题标题】:Option to auto-generate Dockerfile and other deployment tooling in IntelliJ?在 IntelliJ 中自动生成 Dockerfile 和其他部署工具的选项?
【发布时间】:2020-09-12 04:56:50
【问题描述】:

我正在探索使用 Docker 将基于 Tomcat 的 Java 项目容器化的初始步骤。使用 IntelliJ 作为我首选的 IDE,我已经成功:

  • 编写了一个概念验证 Servlet;
  • 设置构建工件以创建生成的 WAR;
  • 使用 IntelliJ Docker 插件和官方 Tomcat Docker 映像之一,设置包含 WAR 内容作为其挂载点之一的容器配置;
  • 通过 IntelliJ 将容器部署到本地 Docker,并确认可以通过本地浏览器成功访问 Servlet。

因此,就基本开发周期而言,我已经启动并运行了。

但是当我最终进行外部部署时(甚至在开发过程中的某个时刻),我将需要添加库和资源并生成一个真正独立的容器:换句话说,我需要从IntelliJ 插件目前正在对“带有挂载点的映像”进行简单部署,以拥有一个完整的 Dockerfile,其中指定了所有相关配置,包括我的挂载被有效地转换为复制相关内容的指令。

现在我的问题是:人们通常如何实现这一目标? IntelliJ 中是否有内置工具可以帮助解决这个问题?在 IntelliJ 的容器部署配置设置中(其中指定了挂载点、基本映像等),似乎没有配置要复制的资源的选项,例如(或“复制到独立容器中而不是从主机 FS 挂载”)。我是否在某处缺少工具/选项,或者 Docker 文件的脚本编写本质上是一个手动过程?还是我只是用我的整个方法来找错树?对于人们通常用于此过程的任何建议,我将不胜感激!

【问题讨论】:

  • 你可以试试 Quarkus,它可以帮助生成 dockerfile 和创建镜像。

标签: docker tomcat intellij-idea


【解决方案1】:

Jib by Google

我认为,Jib 会提供您所需要的。它还为 Maven 和 Gradle 提供了插件,并且可以在 IntelliJ 中通过 Run/Debug Configuration 触发相应的插件(参见最底部的示例)。

What is Jib?

Jib 为您的 Java 应用程序构建优化的 Docker 和 OCI 映像,无需 Docker 守护程序,也无需深入掌握 Docker 最佳实践。它可用作 Maven 和 Gradle 的插件以及 Java 库。

What does Jib do?

Jib 处理将您的应用程序打包到容器映像中的所有步骤。您无需了解创建 Dockerfile 或安装 Docker 的最佳实践。 Jib 将您的应用程序组织成不同的层;依赖项、资源和类;并利用 Docker 镜像层缓存通过仅重建更改来保持快速构建。 Jib 的层组织和较小的基础映像使整体映像大小保持较小,从而提高了性能和可移植性。

配置

您可以查看文档。它包含有关创建和部署 Docker 映像的不同类型配置选项的大量信息。您还可以简单地使用环境变量。

关于您的问题,请检查此部分,例如:adding Arbitrary Files to the Image

在 IntelliJ 的容器部署配置设置中(其中指定了挂载点、基本映像等),似乎没有配置要复制的资源的选项,例如(或“复制到独立容器而不是从主机 FS 挂载”)。

演示

出于演示目的,我使用 Maven 创建了一个简单的项目,其中我还使用了基础映像 tomcat:9.0.36-jdk8-openjdk,顺便说一下,这也是可选的 - 请参阅 Jib WAR Projects

Servlet:

@WebServlet(urlPatterns = {"/hello-world"})
public class HelloWorld extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("Hello World");
    }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mvn-jib-example</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>servlet-hello-world</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>2.5.0</version>
                <configuration>
                    <allowInsecureRegistries>true</allowInsecureRegistries>
                    <from>
                        <image>tomcat:9.0.36-jdk8-openjdk</image>
                    </from>
                    <to>
                        <image>registry.localhost/hello-world</image>
                        <auth>
                            <username>registry_username</username>
                            <password>registry_password</password>
                        </auth>
                        <tags>
                            <tag>latest</tag>
                        </tags>
                    </to>
                    <container>
                        <appRoot>/usr/local/tomcat/webapps/ROOT</appRoot>
                    </container>
                    <extraDirectories>
                        <paths>
                            <path>
                                <from>./src/main/resources/extra-stuff</from>
                                <into>/path/in/docker/image/extra-stuff</into>
                            </path>
                            <path>
                                <from>/absolute/path/to/other/stuff</from>
                                <into>/path/in/docker/image/other-stuff</into>
                            </path>
                        </paths>
                    </extraDirectories>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  • 执行以下目标将动态创建 docker 映像:
mvn clean package jib:dockerBuild
  • 确认图像已创建:
docker image ls
  • 从图像启动容器
docker run --rm -p 8082:8080 registry.localhost/hello-world:latest

结果:

部署

要将映像部署到外部 docker 注册表,您可以查看以下部分:

集成开发环境

最后但同样重要的是,由于您使用的是 IntellIJ IDEA,您可以简单地创建一个 RUN/Debug 配置来通过按钮按钮自动创建和部署图像,例如一种用于构建映像的配置,一种用于将其部署到本地主机,一种用于部署到外部注册表等等。

这里是 maven (see) 的示例:

【讨论】:

    【解决方案2】:

    我现在正在做的项目是使用 Spring-boot,它实际上已经嵌入了 Tomcat。我使用 Docker Gradle 插件(https://plugins.gradle.org/plugin/com.bmuschko.docker-spring-boot-application)来构建 Docker 镜像并将其推送到可以是 docker hub 或 AWS ECR 的注册表。这种组合与 IntelliJ 配合得很好,因为它无论如何都是 Gradle 任务。

    由于是Spring-boot,插件可以基于任何基本的JRE镜像(我用https://hub.docker.com/_/adoptopenjdk)构建镜像,配置最少。完全不需要自己写 Dockerfile。

    docker {
    
            def registryHost = 'xxx.dkr.ecr.us-west-2.amazonaws.com'
    
            springBootApplication {
                   baseImage = "${registryHost}/caelus:springboot-jdk14-openj9"
                   images = ["${registryHost}/caelus:app"]
                   ports = [8080,8081]
                   jvmArgs =['-Djdk.httpclient.allowRestrictedHeaders=content-length']
            }
    }
    

    【讨论】:

      【解决方案3】:

      我建议这些问题:

      总而言之,IntelliJ、Eclipse、VStudio 只是 IDE,因此它们不是在实际环境中部署的选项。

      如果您谈论的是外部部署,您需要一种站点来存储您的 docker 映像,并且至少需要一个持续集成服务器(Jenkins、Travis、Bamboo、Circle CI、buddy.works)

      基本流程

      • 架构师、系统管理员、高级开发人员或具有基础架构技能的人员必须创建 Dockerfile 和其他所需文件。
      • 开发者无需担心 docker、volumes、ports 等,开发者只需要开发代码(在你的情况下是 java)。
      • 开发人员执行 git push
      • 您的持续集成服务器检测到此事件并启动 docker build....
      • 在持续集成服务器 docker build 之后,将新创建的 docker 镜像推送到您的 Docker Hub 存储库
      • 使用某些配置,您的持续集成服务器知道需要部署的位置(如您所说的外部部署)。示例可能是下一个经典环境:测试或登台。在这种情况下,部署只是下载请求的 docker 映像。
      • 如果质量保证团队和自动化测试确保一切正常,您的持续集成服务器将执行最后一步:在您的生产环境中部署 docker 映像,或者如我所说,只需下载 docker 映像。

      您的问题

      Docker 文件的脚本编写本质上是一个手动过程吗?

      正如我所解释的,Dockerfile 是一切的基石。如果您需要手术或您是工匠,它的创作是手动的、有趣的或具有挑战性的:

      • 容器启动时的tomcat用户配置
      • tomcat 高级变量配置
      • 任何高级 tomcat 配置都需要人工操作,但您希望将其自动化。

      tomcat/webapps 中的 Java 战争是一个非常常见的要求,因此您会发现很多 Dockerfile,或者如果符合您的要求,您可以使用 IntelliJ 生成的文件。

      如果您没有为您的 Java 应用找到 Dockerfile,请随时与我联系。

      【讨论】:

      • 感谢您的回复。只是为了澄清一下——这并不是说我缺乏编写 Docker 文件(希望如此!)的心理能力,但如果通常是手动过程,我想了解更多。也可能是在现成的 PaaS 平台上部署战争是我最终要采取的方式——再说一次,我只是想看看如果我决定走这条路,人们通常对 Docker 采取什么方法。跨度>
      • 不幸的是,这将是我做的。所以我对这个过程的技术方面也更感兴趣,而不是“如果其他人做了,你会给他们什么虚假的职位”;-)
      猜你喜欢
      • 2011-04-01
      • 1970-01-01
      • 2013-11-26
      • 1970-01-01
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      相关资源
      最近更新 更多