Spring 在 docker 容器内启动实时重新加载不工作
Spring Boot live reload inside a docker container not working
我们在 docker 容器中有一个 Spring 启动 gradle 项目 运行,它使用 docker 卷。 Spring devtools 实时重新加载功能与以下属性一起使用。
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=.
spring.devtools.restart.additional-exclude=src/main/java/**
我们正在使用 docker 卷来更改容器内的源文件。只要需要实时重新加载,文件 src/main/resources/reload-trigger.txt
就会更新。
容器日志显示重新加载有效,但更改不影响。 重新启动 容器时,更改会反映出来。
例如步骤:
- 使用 GET API 在卷内创建了一个控制器文件,并进行了更新
触发器文件
- GET API 在邮递员中不起作用
- 停止并启动容器
- 现在 API 正在工作
Dockerfile
FROM gradle:5.6.2-jdk8
WORKDIR /app
COPY . /app
RUN ./gradlew getDeps
EXPOSE 8000
CMD ["gradle", "bootRun", "-PskipDownload=true"]
Spring Dev Tools 热重载机制仅 reloads/restarts 来自已构建 class 文件的项目;它不会 compile/build 源文件。因此在 docker 容器内,即使更改了源文件, Java class 文件也不会。因此,更改不会反映出来,新添加的 GET API 也不会发布。
当容器重新启动时,它会再次调用 gradle bootRun
,如 Dockerfile 中指定的那样。这会将更改的 Java 文件构建到 class 文件中,并且更改将被反映出来。
当我们在 IDE 中使用它时,IDE(默认情况下)会在源文件发生更改时构建它。所以 Spring 热重载总是加载更新的 class 文件,但这不会发生在 IDE 之外,除非我们有一些机制来观察源代码更改并构建它们,比如 [=15] =]
这些是我现在的设置。
application.properties
# scan for trigger file from root
# trigger file should not be in classpath, or it will go to infinite build loop
spring.devtools.restart.additional-paths=.
spring.devtools.restart.trigger-file=reload-trigger.txt
Dockerfile
FROM gradle:6.7-jdk11
WORKDIR /app
COPY . /app
EXPOSE 8000
# fetch dependencies
RUN chmod +x start.sh && gradle getDeps
# script which watches source file changes in background and executes bootRun
CMD ["sh", "start.sh"]
start.sh
此文件应位于根目录中,因为 Dockerfile 不应位于 classpath
中
# buildAndReload task, running in background, watches for source changes
(sleep 60; gradle buildAndReload --continuous -PskipDownload=true -x Test)&
gradle bootRun -PskipDownload=true
build.gradle
# -----other codes above----- #
task buildAndReload {
dependsOn build
mustRunAfter build // buildAndReload must run after the source files are built into class files using build task
doLast {
new File(".", "reload-trigger.txt").text = "${System.currentTimeMillis()}" // update trigger file in root folder for hot reload
}
}
使用这些设置,每当更改某些源文件时,就会执行 buildAndReload
任务。由于此任务依赖于 build
任务,因此更新的源代码在此之前内置到 class 文件中。此自定义任务然后更新触发器文件,Spring 加载更新的 class 文件并重新启动应用程序。
我们在 docker 容器中有一个 Spring 启动 gradle 项目 运行,它使用 docker 卷。 Spring devtools 实时重新加载功能与以下属性一起使用。
spring.devtools.restart.enabled=true
spring.devtools.restart.additional-paths=.
spring.devtools.restart.additional-exclude=src/main/java/**
我们正在使用 docker 卷来更改容器内的源文件。只要需要实时重新加载,文件 src/main/resources/reload-trigger.txt
就会更新。
容器日志显示重新加载有效,但更改不影响。 重新启动 容器时,更改会反映出来。
例如步骤:
- 使用 GET API 在卷内创建了一个控制器文件,并进行了更新 触发器文件
- GET API 在邮递员中不起作用
- 停止并启动容器
- 现在 API 正在工作
Dockerfile
FROM gradle:5.6.2-jdk8
WORKDIR /app
COPY . /app
RUN ./gradlew getDeps
EXPOSE 8000
CMD ["gradle", "bootRun", "-PskipDownload=true"]
Spring Dev Tools 热重载机制仅 reloads/restarts 来自已构建 class 文件的项目;它不会 compile/build 源文件。因此在 docker 容器内,即使更改了源文件, Java class 文件也不会。因此,更改不会反映出来,新添加的 GET API 也不会发布。
当容器重新启动时,它会再次调用 gradle bootRun
,如 Dockerfile 中指定的那样。这会将更改的 Java 文件构建到 class 文件中,并且更改将被反映出来。
当我们在 IDE 中使用它时,IDE(默认情况下)会在源文件发生更改时构建它。所以 Spring 热重载总是加载更新的 class 文件,但这不会发生在 IDE 之外,除非我们有一些机制来观察源代码更改并构建它们,比如 [=15] =]
这些是我现在的设置。
application.properties
# scan for trigger file from root
# trigger file should not be in classpath, or it will go to infinite build loop
spring.devtools.restart.additional-paths=.
spring.devtools.restart.trigger-file=reload-trigger.txt
Dockerfile
FROM gradle:6.7-jdk11
WORKDIR /app
COPY . /app
EXPOSE 8000
# fetch dependencies
RUN chmod +x start.sh && gradle getDeps
# script which watches source file changes in background and executes bootRun
CMD ["sh", "start.sh"]
start.sh
此文件应位于根目录中,因为 Dockerfile 不应位于 classpath
中# buildAndReload task, running in background, watches for source changes
(sleep 60; gradle buildAndReload --continuous -PskipDownload=true -x Test)&
gradle bootRun -PskipDownload=true
build.gradle
# -----other codes above----- #
task buildAndReload {
dependsOn build
mustRunAfter build // buildAndReload must run after the source files are built into class files using build task
doLast {
new File(".", "reload-trigger.txt").text = "${System.currentTimeMillis()}" // update trigger file in root folder for hot reload
}
}
使用这些设置,每当更改某些源文件时,就会执行 buildAndReload
任务。由于此任务依赖于 build
任务,因此更新的源代码在此之前内置到 class 文件中。此自定义任务然后更新触发器文件,Spring 加载更新的 class 文件并重新启动应用程序。