網頁

2020/12/12

String Boot Jib Maven build docker image

使用GoogleContainerTools下的Jib maven plugin build Spring Boot docker image。

原本建置Spring Boot應用程式的docker image的步驟如下:

  1. build Spring Boot jar
  2. 撰寫Dockerfile
  3. 執行docker build

例如「Docker build Spring Boot docker image」這篇就是依以上步驟來建置docker image。


除了以上還可使用Google的Jib maven plugin來簡化以上步驟。Jib build的docker image若push到docker registry甚至不需要安裝Docker。

下圖是原本Docker build的過程。


+---------+     +---------+           +-----------------------------------------------+
| Project |---->|   JAR   |-------+   |   Docker Daemon                               |
+---------+     +---------+       |   | +---------------+  build  +-----------------+ |     +------------------+
                                  +---->| Build context |-------->| Container Image |------>| Container Image  |
                +------------+    |   | +---------------+         | (docker cache)  | |     | (registry)       |
                | Dockerfile |----+   |                           +-----------------+ |     +------------------+
                +------------+        +-----------------------------------------------+


下圖則是用Jib build的過程。

+---------+       Jib      +------------------+
| Project |--------------->| Container Image  |
+---------+                | (registry)       |
                           +------------------+


範例環境:

  • Java 8
  • Spring Boot 2.3.2.RELEASE
  • Maven 3.6.3
  • Docker 19.03.12

本範例僅在本機用Jib build image到本機的Docker daemon,所以仍要安裝Docker。

首先建立Spring Boot專案

參考pom.xml設定。


application.properties設定如下。

#context path
server.servlet.context-path=/demo
#port
server.port=8080

新增一個DemoController處理請求。

package com.abc.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello World Spring Boot build by Jib Maven plugin";
    }
}

開啟命令列工具(終端機 or cmd)將工作目錄移到Spring Boot專案的根目錄下,輸入
mvn compile com.google.cloud.tools:jib-maven-plugin:2.7.0:dockerBuild
用Jib把此Spring Boot專案建置為docker image。如果是第一次用Jib build則過程中會從maven central下載依賴的函式庫。

~/../spring-boot-demo$ mvn compile com.google.cloud.tools:jib-maven-plugin:2.7.0:dockerBuild
[INFO] Scanning for projects...
Downloading from central: https://repo.maven.apache.org/maven2/com/google/cloud/tools/jib-maven-plugin/2.7.0/jib-maven-plugin-2.7.0.pom
Downloaded from central: https://repo.maven.apache.org/maven2/com/google/cloud/tools/jib-maven-plugin/2.7.0/jib-maven-plugin-2.7.0.pom (4.1 kB at 2.9 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/com/google/cloud/tools/jib-maven-plugin/2.7.0/jib-maven-plugin-2.7.0.jar
Downloaded from central: https://repo.maven.apache.org/maven2/com/google/cloud/tools/jib-maven-plugin/2.7.0/jib-maven-plugin-2.7.0.jar (537 kB at 541 kB/s)
[INFO]
[INFO] ----------------------< com.abc:spring-boot-demo >----------------------
[INFO] Building spring-boot-demo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ spring-boot-demo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ spring-boot-demo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /../spring-boot-demo/target/classes
[INFO]
[INFO] --- jib-maven-plugin:2.7.0:dockerBuild (default-cli) @ spring-boot-demo ---
Downloading from central: ...
...
[INFO] Tagging image with generated image reference spring-boot-demo:0.0.1-SNAPSHOT. If you'd like to specify a different tag, you can set the <to><image> parameter in your pom.xml, or use the -Dimage=<MY IMAGE> commandline flag.
[WARNING] 'mainClass' configured in 'maven-jar-plugin' is not a valid Java class: ${start-class}
[INFO]
[INFO] Containerizing application to Docker daemon as spring-boot-demo:0.0.1-SNAPSHOT...
[WARNING] Base image 'gcr.io/distroless/java:8' does not use a specific image digest - build may not be reproducible
[INFO] Using base image with digest: sha256:90596f62a8ec0701d00845b85dfccf7f53b5e0bb3c49e275d7f19ea6c3e4565d
[INFO]
[INFO] Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, com.abc.demo.DemoApplication]
[INFO]
[INFO] Built image to Docker daemon as spring-boot-demo:0.0.1-SNAPSHOT
[INFO] Executing tasks:
[INFO] [==============================] 100.0% complete
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:17 min
[INFO] Finished at: 2020-12-12T13:08:43+08:00
[INFO] ------------------------------------------------------------------------

build結束後在命令列輸入docker images即可看到建置好的專案image。image的REPOSITORY名稱預設使用Maven專案pom.xml<artifactId>TAG則為<version>

$ docker images
REPOSITORY                         TAG                 IMAGE ID            CREATED             SIZE
spring-boot-demo                   0.0.1-SNAPSHOT      cc8fbb17a345        50 years ago        148MB

建立時間(CREATED)在50 years ago(or 48+ years ago)是因為Jib為了達到image的再製性(reproducibility)所以把timestamp移除的結果。

輸入$ docker run -p 8080:8080 --name demo spring-boot-demo:0.0.1-SNAPSHOT啟動spring-boot-demo container。

$ docker run -p 8080:8080 --name demo spring-boot-demo:0.0.1-SNAPSHOT

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

2020-12-12 09:44:56.770  INFO 1 --- [           main] c.a.d.DemoApplication                    : Starting DemoApplication on 4c779dd36d5a with PID 1 (/app/classes started by root in /)
2020-12-12 09:44:56.786  INFO 1 --- [           main] c.a.d.DemoApplication                    : No active profile set, falling back to default profiles: default
2020-12-12 09:44:58.247  INFO 1 --- [           main] o.s.b.w.e.t.TomcatWebServer              : Tomcat initialized with port(s): 8080 (http)
2020-12-12 09:44:58.283  INFO 1 --- [           main] o.a.c.c.StandardService                  : Starting service [Tomcat]
2020-12-12 09:44:58.284  INFO 1 --- [           main] o.a.c.c.StandardEngine                   : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-12-12 09:44:58.396  INFO 1 --- [           main] o.a.c.c.C.[.[.[/demo]                    : Initializing Spring embedded WebApplicationContext
2020-12-12 09:44:58.397  INFO 1 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1533 ms
2020-12-12 09:44:58.693  INFO 1 --- [           main] o.s.s.c.ThreadPoolTaskExecutor           : Initializing ExecutorService 'applicationTaskExecutor'
2020-12-12 09:44:59.002  INFO 1 --- [           main] o.s.b.w.e.t.TomcatWebServer              : Tomcat started on port(s): 8080 (http) with context path '/demo'
2020-12-12 09:44:59.019  INFO 1 --- [           main] c.a.d.DemoApplication                    : Started DemoApplication in 3.006 seconds (JVM running for 4.172)

在瀏覽器位址輸入http://localhost:8080/demo/hello會回傳以下。這邊的Spring Boot即為運行的spring-boot-demo container。



輸入docker ps檢視運行中的spring-boot-demo container。

$ docker ps
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                    NAMES
4c779dd36d5a        spring-boot-demo:0.0.1-SNAPSHOT   "java -cp /app/resou…"   9 minutes ago       Up 4 seconds        0.0.0.0:8080->8080/tcp   demo

參考github


沒有留言:

張貼留言