试用Spring Boot 2.3.0 M1版本中新引入的 使用原生云构建包构建Docker镜像的功能

引发事件的原因

SpringBoot 2.3.0 M1已发布。

有各种各样的改进和删除不必要的功能,但在查看发布说明时发现了一件令人关注的事情,我想尝试使用云原生构建包构建Docker镜像。

在发布说明中,包含了以下内容。

通过 spring-boot:build-image 目标和 bootBuildImage 任务,Maven 和 Gradle 插件已经支持使用 Cloud Native Buildpacks 构建 Docker 镜像。

据说可以使用Maven或Gradle插件创建Docker镜像。
我想立即尝试一下,并对这项活动进行总结。

如何开始

以前设定相同,
使用Spring Initializr创建应用模板。
创建之后,想要获取环境信息,所以也启用了SpringBoot Actuator。

立即创建DockerImage。在创建镜像的环境中需要启动DockerDeamon,请注意这一点。

以前构建Spring Boot应用程序的Docker镜像需要按照以下步骤进行:
1. 使用mvn package命令创建应用程序的Jar文件。
2. 在Dockerfile中记录要创建的Docker镜像的具体内容。
3. 使用docker build命令创建镜像。

    Dockerfileの設定例
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

使用Cloud Native Buildpacks可以在一步中构建Docker镜像,无需执行上述步骤。对于Maven,只需执行mvn spring-boot:build-image命令,对于Gradle,只需执行gradle bootBuildImage命令。Cloud Native Buildpacks的功能可以读取源代码并自动补充所需的Dockerfile配置信息。

$ mvn spring-boot:build-image
[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------< com.example:demo >--------------------------
[INFO] Building demo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] >>> spring-boot-maven-plugin:2.3.0.M1:build-image (default-cli) > package @ demo >>>
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ demo ---
[INFO] Nothing to compile - all classes are up to date

中略

[INFO]  > Running builder
[INFO]     [builder]
[INFO]     [builder]     Cloud Foundry OpenJDK Buildpack v1.0.80
[INFO]     [builder]       OpenJDK JRE 11.0.5: Reusing cached layer
[INFO]     [builder]
[INFO]     [builder]     Cloud Foundry JVM Application Buildpack v1.0.113
[INFO]     [builder]       Executable JAR: Reusing cached layer
[INFO]     [builder]       Process types:
[INFO]     [builder]         executable-jar: java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[INFO]     [builder]         task:           java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[INFO]     [builder]         web:            java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[INFO]     [builder]
[INFO]     [builder]     Cloud Foundry Spring Boot Buildpack v1.0.157
[INFO]     [builder]       Spring Boot 2.3.0.M1: Reusing cached layer
[INFO]     [builder]       Process types:
[INFO]     [builder]         spring-boot: java -cp $CLASSPATH $JAVA_OPTS com.example.demo.DemoApplication
[INFO]     [builder]         task:        java -cp $CLASSPATH $JAVA_OPTS com.example.demo.DemoApplication
[INFO]     [builder]         web:         java -cp $CLASSPATH $JAVA_OPTS com.example.demo.DemoApplication
[INFO]     [builder]
[INFO]     [builder]     Cloud Foundry Spring Auto-reconfiguration Buildpack v1.0.159
[INFO]     [builder]       Spring Auto-reconfiguration 2.11.0: Reusing cached layer
[INFO]
[INFO]  > Running exporter
[INFO]     [exporter]    Reusing layer 'app'
[INFO]     [exporter]    Reusing layer 'config'
[INFO]     [exporter]    Reusing layer 'launcher'
[INFO]     [exporter]    Reusing layer 'org.cloudfoundry.openjdk:openjdk-jre'
[INFO]     [exporter]    Reusing layer 'org.cloudfoundry.jvmapplication:executable-jar'
[INFO]     [exporter]    Reusing layer 'org.cloudfoundry.springboot:spring-boot'
[INFO]     [exporter]    Reusing layer 'org.cloudfoundry.springautoreconfiguration:auto-reconfiguration'
[INFO]     [exporter]    *** Images (89a7e99f9c15):
[INFO]     [exporter]          docker.io/library/demo:0.0.1-SNAPSHOT
[INFO]
[INFO]  > Running cacher
[INFO]     [cacher]      Reusing layer 'org.cloudfoundry.openjdk:2f08c469c9a8adea1b6ee3444ba2a8242a7e99d87976a077faf037a9eb7f884b'
[INFO]     [cacher]      Reusing layer 'org.cloudfoundry.jvmapplication:executable-jar'
[INFO]     [cacher]      Reusing layer 'org.cloudfoundry.springboot:spring-boot'
[INFO]     [cacher]      Reusing layer 'org.cloudfoundry.springautoreconfiguration:46ab131165317d91fd4ad3186abf755222744e2d277dc413def06f3ad45ab150'
[INFO]
[INFO] Successfully built image 'docker.io/library/demo:0.0.1-SNAPSHOT'
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:01 min
[INFO] Finished at: 2020-02-08T15:30:43+09:00
[INFO] ------------------------------------------------------------------------

第一次可能需要花费一些时间来下载基础镜像,但第二次及之后就可以在上述的时间内完成。

现在,让我们确认一下Docker镜像是否已经创建成功。

docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED              SIZE
demo                                 0.0.1-SNAPSHOT      89a7e99f9c15        About a minute ago   226MB

确保已经准备就绪,启动过程与普通的DockerImage相同。在这里,我们使用docker run -it -p8080:8080 demo:0.0.1-SNAPSHOT进行启动。

docker run -it -p8080:8080 demo:0.0.1-SNAPSHOT

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::             (v2.3.0.M1)

2020-02-08 06:33:43.540  WARN 1 --- [           main] pertySourceApplicationContextInitializer : Skipping 'cloud' property source addition because not in a cloud
2020-02-08 06:33:43.570  WARN 1 --- [           main] nfigurationApplicationContextInitializer : Skipping reconfiguration because not in a cloud
2020-02-08 06:33:43.635  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on 40fbed8bc770 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2020-02-08 06:33:43.636  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2020-02-08 06:33:48.387  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-02-08 06:33:48.456  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-02-08 06:33:48.466  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.30]
2020-02-08 06:33:48.738  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-02-08 06:33:48.740  INFO 1 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 4841 ms
2020-02-08 06:33:50.208  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-02-08 06:33:50.900  INFO 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 14 endpoint(s) beneath base path '/actuator'
2020-02-08 06:33:51.122  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-02-08 06:33:51.142  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 9.779 seconds (JVM running for 12.428)

一切正常,应用程序已成功启动。由于上次使用过该应用程序,Actuator仍然处于启用状态。让我们获取一下env的信息。

curl localhost:8080/actuator/env | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8753    0  8753    0     0  10130      0 --:--:-- --:--:-- --:--:-- 10130
{
  "activeProfiles": [],
  "propertySources": [
    {
      "name": "server.ports",
      "properties": {
        "local.server.port": {
          "value": 8080
        }
      }
    },
    {
      "name": "servletContextInitParams",
      "properties": {}
    },
    {
      "name": "systemProperties",
      "properties": {
        "awt.toolkit": {
          "value": "sun.awt.X11.XToolkit"
        },
        "java.specification.version": {
          "value": "11"
        },
        "sun.cpu.isalist": {
          "value": ""
        },
        "sun.jnu.encoding": {
          "value": "ANSI_X3.4-1968"
        },
        "java.class.path": {
          "value": "/layers/org.cloudfoundry.springautoreconfiguration/auto-reconfiguration/java-buildpack-auto-reconfiguration-2.11.0.RELEASE.jar:/workspace/BOOT-INF/classes:/workspace/BOOT-INF/lib/HdrHistogram-2.1.11.jar:/workspace/BOOT-INF/lib/LatencyUtils-2.0.3.jar:/workspace/BOOT-INF/lib/jackson-annotations-2.10.1.jar:/workspace/BOOT-INF/lib/jackson-core-2.10.1.jar:/workspace/BOOT-INF/lib/jackson-databind-2.10.1.jar:/workspace/BOOT-INF/lib/jackson-datatype-jdk8-2.10.1.jar:/workspace/BOOT-INF/lib/jackson-datatype-jsr310-2.10.1.jar:/workspace/BOOT-INF/lib/jackson-module-parameter-names-2.10.1.jar:/workspace/BOOT-INF/lib/jakarta.annotation-api-1.3.5.jar:/workspace/BOOT-INF/lib/jakarta.el-3.0.3.jar:/workspace/BOOT-INF/lib/jul-to-slf4j-1.7.29.jar:/workspace/BOOT-INF/lib/log4j-api-2.12.1.jar:/workspace/BOOT-INF/lib/log4j-to-slf4j-2.12.1.jar:/workspace/BOOT-INF/lib/logback-classic-1.2.3.jar:/workspace/BOOT-INF/lib/logback-core-1.2.3.jar:/workspace/BOOT-INF/lib/micrometer-core-1.3.3.jar:/workspace/BOOT-INF/lib/slf4j-api-1.7.29.jar:/workspace/BOOT-INF/lib/snakeyaml-1.25.jar:/workspace/BOOT-INF/lib/spring-aop-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-beans-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-boot-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-actuator-autoconfigure-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-autoconfigure-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-actuator-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-json-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-logging-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-tomcat-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-boot-starter-web-2.3.0.M1.jar:/workspace/BOOT-INF/lib/spring-context-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-core-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-expression-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-jcl-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-web-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/spring-webmvc-5.2.3.RELEASE.jar:/workspace/BOOT-INF/lib/tomcat-embed-core-9.0.30.jar:/workspace/BOOT-INF/lib/tomcat-embed-websocket-9.0.30.jar:/workspace"
        },
        "java.vm.vendor": {
          "value": "AdoptOpenJDK"
        },
        "sun.arch.data.model": {
          "value": "64"
        },
        "java.vendor.url": {
          "value": "https://adoptopenjdk.net/"
        },
        "catalina.useNaming": {
          "value": "false"
        },
        "user.timezone": {
          "value": "GMT"
        },
        "os.name": {
          "value": "Linux"
        },
        "java.vm.specification.version": {
          "value": "11"
        },
        "sun.java.launcher": {
          "value": "SUN_STANDARD"
        },
        "user.country": {
          "value": "US"
        },
        "sun.boot.library.path": {
          "value": "/layers/org.cloudfoundry.openjdk/openjdk-jre/lib"
        },
        "sun.java.command": {
          "value": "******"
        },
        "jdk.debug": {
          "value": "release"
        },
        "sun.cpu.endian": {
          "value": "little"
        },
        "user.home": {
          "value": "/home/cnb"
        },
        "user.language": {
          "value": "en"
        },
        "java.specification.vendor": {
          "value": "Oracle Corporation"
        },
        "java.version.date": {
          "value": "2019-10-15"
        },
        "java.home": {
          "value": "/layers/org.cloudfoundry.openjdk/openjdk-jre"
        },
        "file.separator": {
          "value": "/"
        },
        "java.vm.compressedOopsMode": {
          "value": "32-bit"
        },
        "line.separator": {
          "value": "\n"
        },
        "java.specification.name": {
          "value": "Java Platform API Specification"
        },
        "java.vm.specification.vendor": {
          "value": "Oracle Corporation"
        },
        "java.awt.graphicsenv": {
          "value": "sun.awt.X11GraphicsEnvironment"
        },
        "java.awt.headless": {
          "value": "true"
        },
        "sun.management.compiler": {
          "value": "HotSpot 64-Bit Tiered Compilers"
        },
        "java.runtime.version": {
          "value": "11.0.5+10"
        },
        "user.name": {
          "value": "cnb"
        },
        "path.separator": {
          "value": ":"
        },
        "os.version": {
          "value": "4.9.184-linuxkit"
        },
        "java.runtime.name": {
          "value": "OpenJDK Runtime Environment"
        },
        "file.encoding": {
          "value": "ANSI_X3.4-1968"
        },
        "spring.beaninfo.ignore": {
          "value": "true"
        },
        "java.vm.name": {
          "value": "OpenJDK 64-Bit Server VM"
        },
        "java.vendor.version": {
          "value": "AdoptOpenJDK"
        },
        "java.vendor.url.bug": {
          "value": "https://github.com/AdoptOpenJDK/openjdk-build/issues"
        },
        "java.io.tmpdir": {
          "value": "/tmp"
        },
        "catalina.home": {
          "value": "/tmp/tomcat.9057283283640867778.8080"
        },
        "java.version": {
          "value": "11.0.5"
        },
        "user.dir": {
          "value": "/workspace"
        },
        "os.arch": {
          "value": "amd64"
        },
        "java.vm.specification.name": {
          "value": "Java Virtual Machine Specification"
        },
        "PID": {
          "value": "1"
        },
        "java.awt.printerjob": {
          "value": "sun.print.PSPrinterJob"
        },
        "sun.os.patch.level": {
          "value": "unknown"
        },
        "catalina.base": {
          "value": "/tmp/tomcat.9057283283640867778.8080"
        },
        "java.library.path": {
          "value": "/layers/org.cloudfoundry.openjdk/openjdk-jre/lib:/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib"
        },
        "java.vendor": {
          "value": "AdoptOpenJDK"
        },
        "java.vm.info": {
          "value": "mixed mode"
        },
        "java.vm.version": {
          "value": "11.0.5+10"
        },
        "sun.io.unicode.encoding": {
          "value": "UnicodeLittle"
        },
        "java.class.version": {
          "value": "55.0"
        }
      }

後略

你们使用的是AdoptOpenJDK的11版本进行Java的实现,对吗?操作系统看起来是类似于Linux。

总结

由于不需要编写Dockerfile,即使没有Docker知识,也可以轻松地创建Docker镜像。虽然需要确认规范和细节才能立即投入生产环境,但能够轻松创建Docker镜像可能是一个优势,不是吗?

我已将所使用的源代码放在以下位置。
供参考使用。

广告
将在 10 秒后关闭
bannerAds