java - Docker 上的 Spring 开发

标签 java spring maven docker gradle

我对 Java 和 Spring 还很陌生。我正在寻找一个容器化的解决方案,它监视 src 文件夹,重建项目并利用 Spring devtools hotswap 重新加载更改的类。

我进行了搜索,但一直在寻找生产就绪的容器,构建和运行的步骤是分开的。我尝试使用 2 种不同的容器,一种使用持续构建的 Gradle (gradle build --continuous),另一种执行构建结果:

version: '3.7'
services:

  builder:
    image: gradle:jdk11
    working_dir: /home/gradle/project
    volumes:
      - ./:/home/gradle/project
    command: gradle build --continuous

  api:
    image: openjdk:11-slim
    volumes:
    - ./build/classes:/app
    command: java -classpath /app/java/main com.example.Application

失败是因为 Java 在 api 容器中找不到依赖项(Spring、devtools、h2 等),而且我不知道如何让 Gradle 包含外部 jar在构建文件夹中。我想做点什么like this , 除了这个例子已经过时了。

不过,我一直认为可能有更优雅、更简单的解决方案。它不必与 Gradle 一起使用,如果可以的话,它可以是 Maven! :)

我知道很多IDE都支持自动构建和devtools,我只想在Docker上实现。这样,我就会有一个在存储库上而不是在 IDE 配置上的开发工作流,并且几乎与任何开发环境兼容。这是个坏主意吗?

最佳答案

最后,我找到了一个非常有效的解决方案,只有一个警告。 这当然是一个开发环境,旨在快速更改文件、自动构建和刷新 Spring 应用程序。 它不用于生产。

构建过程委托(delegate)给监视更改的 Gradle 容器。因为 Gradle 有 Incremental Compilation ,即使对于大型项目,它也应该具有良好的扩展性。

应用程序本身在 openjdk:11-slim 上执行。由于它运行 .class 文件,SpringBoot 知道它是 dev-env 并激活它的 devtools

这是我的docker-compose.yml:

version: '3.7'
services:

  builder:
    image: gradle:jdk11
    working_dir: /home/gradle/project
    volumes:
      - ./build:/home/gradle/project/build
      - ./src:/home/gradle/project/src
      - ./build.gradle:/home/gradle/project/build.gradle
    command: gradle build --continuous -x test -x testClasses

  api:
    image: openjdk:13-alpine
    volumes:
    - ./build:/app
    depends_on:
      - builder
    command: java -cp "/app/classes/java/main:/app/dependencies/*:/app/resources/main" com.example.Application

这是我的build.gradle:

plugins {
    id 'org.springframework.boot' version '2.2.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.1.0-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

task copyLibs(type: Copy) {
    from configurations.runtimeClasspath
    into "${buildDir}/dependencies"
}

build.dependsOn(copyLibs)

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.h2database:h2'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

总而言之,整个过程需要 5 秒的时间来重建和热交换源代码中的更改。不像 webpack 那样快,但仍然可以接受。以这种方式拥有它的最大优势是它驻留在代码上,每个人都可以让它工作,无论他们的工作站是什么。

注意事项?第一次运行时,构建文件夹为空,api 容器无法启动。您必须等待 builder 完成其工作,然后重新启动 api

我仍然希望有更好的解决方案,我鼓励您发布比这更流畅的所有内容。

关于java - Docker 上的 Spring 开发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59129211/

相关文章:

java - 何时在 Mono 上使用 .flatMap() 而不是仅仅对值调用函数?

java - 表格:select in spring MVC

java - 设置操作系统环境变量后,Apache Maven install "' mvn' not Recognized as an internal or external command"?

java - Firebase - (具有多个子节点用户唯一键的 DataSnapshot ) - 空对象引用

java - Collections 类中 checkedList 方法的用途

java - 在 java @configuration 类中初始化 init 方法属性的更好方法

java - 如何从 maven Central 构建 nifi 处理器 nar 文件和依赖项

java - 我如何使用maven构建这个java项目?

java - 根据数据库值动态加载jTable中的Image

java - 我可以使用哪种设计模式?