docker 容器内的 Spring Boot 实时重新加载不起作用

2024-05-07

我们有一个在 docker 容器内运行的 Spring boot 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 热重载机制仅从已构建的类文件中重新加载/重新启动项目;它不会编译/构建源文件。因此,在 docker 容器内,即使源文件发生更改,Java 类文件也不会更改。因此,更改不会反映,并且新添加的 GET API 将不会发布。

当容器重新启动时,它会再次调用gradle bootRun如 Dockerfile 中指定。这会将更改的 Java 文件构建到类文件中,并且更改将得到反映。

当我们在 IDE 中使用它时,IDE(默认情况下)会在源文件发生更改时构建它。因此 Spring 热重载总是加载更新的类文件,但这不会在 IDE 之外发生,除非我们有某种机制来监视源代码更改并构建它们,例如gradle build --continuous

这些是我现在的设置。

应用程序属性

# 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 不应位于类路径中

# buildAndReload task, running in background, watches for source changes
(sleep 60; gradle buildAndReload --continuous -PskipDownload=true -x Test)&
gradle bootRun -PskipDownload=true

构建.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任务之前,更新的源代码已内置到类文件中。然后,此自定义任务更新触发器文件,Spring 加载更新的类文件并重新启动应用程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

docker 容器内的 Spring Boot 实时重新加载不起作用 的相关文章

随机推荐