我对 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/