在使用Spring Boot Devtools和Jib进行组合时,有时希望在容器运行时禁用Devtools,这是一个讨论
怎么了? le?)
我认为在使用Spring Boot创建Docker镜像时,使用Cloud Native Buildpacks是标准做法。
当我试图使用Jib构建时,发现在依赖关系中包含Spring Boot Devtools会遇到一些困难,所以我将这个问题记下来。
发生的事件和解决方法
遇到的问题是,在包含Spring Boot Devtools依赖的情况下使用Jib创建并执行Docker镜像时,导致在Docker容器运行时Spring Boot Devtools被激活了。
据写着,Spring Boot Devtools在打包执行时会被禁用。
当运行完全打包的应用程序时,开发者工具会自动禁用。如果您的应用程序从java -jar启动,或者从特殊的类加载器启动,则被视为“生产应用程序”。
使用Spring Boot / 开发者工具进行开发
从一开始就认为,在生产环境中,应该不启用Devtool。
在生产环境中运行开发工具是一种安全风险,因此这是不能被允许的。
在这里,我会看一下Jib文档中关于专门针对Spring Boot的描述。
常见问题解答(FAQ)/ Jib CLI / jar命令如何支持Spring Boot JAR包?
推荐的是以“Exploded Mode”模式执行,执行格式为java -cp /app org.springframework.boot.loader.JarLauncher。
(实际运行时,感觉有些不同…)
然后,问题是如果不做任何更改,Spring Boot Devtools将会被启用。
要禁用它,只需在创建Docker镜像的时候将Spring Boot Devtools的作用域设置为provided,这样在打包时就不会包含进去了。
或者,您可以在运行时使用-Dspring.devtools.restart.enabled=false进行指定。
如果可以的话,我认为在创建Docker镜像时最好将其排除掉才更保险。
那么,我们来确认一下实际操作。
环境
这次的环境是这里。
$ java --version
openjdk 11.0.15 2022-04-19
OpenJDK Runtime Environment (build 11.0.15+10-Ubuntu-0ubuntu0.20.04.1)
OpenJDK 64-Bit Server VM (build 11.0.15+10-Ubuntu-0ubuntu0.20.04.1, mixed mode, sharing)
$ mvn --version
Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: /home/charon/.sdkman/candidates/maven/current
Java version: 11.0.15, vendor: Private Build, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-120-generic", arch: "amd64", family: "unix"
$ docker version
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:02:57 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.17
API version: 1.41 (minimum version 1.12)
Go version: go1.17.11
Git commit: a89b842
Built: Mon Jun 6 23:01:03 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.6
GitCommit: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
runc:
Version: 1.1.2
GitCommit: v1.1.2-0-ga916309
docker-init:
Version: 0.19.0
GitCommit: de40ad0
创建一个Spring Boot项目,并添加Jib。
首先,创建一个Spring Boot项目。在依赖项中,我已经包含了web和devtools。
$ curl -s https://start.spring.io/starter.tgz \
-d bootVersion=2.7.0 \
-d javaVersion=11 \
-d name=devtools-with-jib \
-d groupId=com.example \
-d artifactId=devtools-with-jib \
-d version=0.0.1-SNAPSHOT \
-d packageName=com.example.spring \
-d dependencies=web,devtools \
-d baseDir=devtools-with-jib | tar zxvf -
进入项目内部。
$ cd devtools-with-jib
请查看以下依存关系。
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
在这里添加Jib的Maven插件。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.1</version>
</plugin>
</plugins>
</build>
现在我们来创建源代码。
暂时删除生成的源代码。
$ rm src/main/java/com/example/spring/DevtoolsWithJibApplication.java src/test/java/com/example/spring/DevtoolsWithJibApplicationTests.java
创建一个简单的源代码。
package com.example.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class App {
public static void main(String... args) {
SpringApplication.run(App.class, args);
}
@GetMapping
public String hello() {
return "Hello World";
}
}
我会尝试确认
那么,我们来创建一个Docker镜像。
$ mvn package jib:dockerBuild
## 以下でも同じ
$ mvn compile jib:dockerBuild
执行。
$ docker container run -it --rm -p 8080:8080 --name app devtools-with-jib:0.0.1-SNAPSHOT
从日志中看,可以知道Spring Boot Devtools已经启用了。
2022-06-22 15:25:21.171 INFO 1 --- [ restartedMain] com.example.spring.App : Starting App using Java 11.0.15 on 173c614374c4 with PID 1 (/app/classes started by root in /)
2022-06-22 15:25:21.177 INFO 1 --- [ restartedMain] com.example.spring.App : No active profile set, falling back to 1 default profile: "default"
2022-06-22 15:25:21.563 INFO 1 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2022-06-22 15:25:21.569 INFO 1 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2022-06-22 15:25:26.686 INFO 1 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
由于主题是“restartedMain”,所以。
容器内的执行命令大致如下。
$ docker container exec -it app sh -c 'ps -ef | grep java | grep -v grep'
root 1 0 62 15:25 pts/0 00:00:39 java -cp @/app/jib-classpath-file com.example.spring.App
当然,虽然我还是以平常的方式运动。
$ curl localhost:8080
Hello World
所以,由于包含了Spring Boot Devtools有点讨厌,我们要想办法解决一下。
更改Spring Boot Devtools的作用域。
首先,让我们按照Jib的问题所提到的,尝试修改Spring Boot Devtools的范围。
这是利用了「provided」的条件,使其在打包时不再包含。
将范围定义为属性
Note: The provided translation is in Simplified Chinese.
<properties>
<java.version>11</java.version>
<devtools.dependency.scope>runtime</devtools.dependency.scope>
</properties>
将Spring Boot Devtools的scope设置为runtime为默认值。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>${devtools.dependency.scope}</scope>
<optional>true</optional>
</dependency>
最后,在打包时指定范围的方式如下。
$ mvn package jib:dockerBuild -Ddevtools.dependency.scope=provided
这样一来,Spring Boot Devtools就不能正常工作了。
2022-06-22 15:29:28.859 INFO 1 --- [ main] com.example.spring.App : Starting App using Java 11.0.15 on a1826ae55975 with PID 1 (/app/classes started by root in /)
2022-06-22 15:29:28.862 INFO 1 --- [ main] com.example.spring.App : No active profile set, falling back to 1 default profile: "default"
2022-06-22 15:29:30.187 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
将spring.devtools.restart.enabled属性设置为false。
另一种方法是将spring.devtools.restart.enabled属性设置为false。
本次是将Jib的Maven插件的jvmFlags参数指定为指定的选项。
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<container>
<jvmFlags>
<jvmFlag>-Dspring.devtools.restart.enabled=false</jvmFlag>
</jvmFlags>
</container>
</configuration>
</plugin>
创建容器镜像。
$ mvn package jib:dockerBuild
在这里,结果与刚才一样。
2022-06-22 15:32:11.576 INFO 1 --- [ main] com.example.spring.App : Starting App using Java 11.0.15 on dfa3860ded97 with PID 1 (/app/classes started by root in /)
2022-06-22 15:32:11.578 INFO 1 --- [ main] com.example.spring.App : No active profile set, falling back to 1 default profile: "default"
2022-06-22 15:32:11.658 INFO 1 --- [ main] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2022-06-22 15:32:12.823 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)