Cloud Native Buildpacksの対応

# はじめに
以下の通り、Spring Boot2.3からはDockerImageの作成が簡易になっている。k8s上ではDockerImageがベースであり、これが簡易に作成されるのはCI/CDの点から利点だと考えている。
https://qiita.com/omix222/items/d305f68f3f021529ec94


# 実施内容
•	build.gradleは、特に特別な対応は不要。pluginのjavaでtaskに追加される。
•	以下、buildspec.yml内にて、bootBuildImageを実行のみ。

```buildspec.yml  
version: 0.2

env:
  variables:
    IMAGE_NAME: "spring-boot-democlient"
    AWS_ACCOUNT: "XXXXXXXXXXXX"
    # TODO: 本来はgradleのartifactから取ってくる必要がある。
    # See Also https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/gradle-plugin/reference/html/#build-image-customization
    IMAGE_REPO: "docker.io/library/spring-boot-democlient"
phases:
  install:
    commands:
      - chmod +x ./gradlew
      - touch gradle.properties
      - |
        cat <<EOL >> gradle.properties
        org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m
        EOL
        
      - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay&
      - timeout 15 sh -c "until docker info; do echo .; sleep 1; done"

  pre_build:
    commands:
      - echo build start on `date`
      - $(aws ecr get-login --no-include-email)
      
  build:
    commands:
      - ./gradlew bootBuildImage --imageName=${IMAGE_NAME}
      - docker tag ${IMAGE_REPO}:latest ${AWS_ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_REPO}:${IMAGE_TAG}
  post_build:
    commands:
      - docker push ${AWS_ACCOUNT}.dkr.ecr.ap-northeast-1.amazonaws.com/${IMAGE_REPO}:${IMAGE_TAG}
cache:
  paths:
    - /root/.gradle/caches/**/*
    - /root/.gradle/wrapper/**/*
```

## 注意点
`./gradlew bootImageBuild`は--imageNameを設定してもdocker.io/library/配下に作られるので、ECRのリポジトリの方もそうやって作る必要がある。

## 環境情報
本DockerImageをEKS上で動作させた際の、SpringBootAcutatorで取得できる環境情報

```environment  
{
	"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": "/workspace"
				},
				"java.vm.vendor": {
					"value": "BellSoft"
				},
				"sun.arch.data.model": {
					"value": "64"
				},
				"java.vendor.url": {
					"value": "https://bell-sw.com/"
				},
				"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/paketo-buildpacks_bellsoft-liberica/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.security.properties": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties"
				},
				"java.version.date": {
					"value": "2020-04-14"
				},
				"java.home": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/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.7+10-LTS"
				},
				"user.name": {
					"value": "cnb"
				},
				"path.separator": {
					"value": ":"
				},
				"os.version": {
					"value": "4.14.181-140.257.amzn2.x86_64"
				},
				"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.url.bug": {
					"value": "https://bell-sw.com/support"
				},
				"java.io.tmpdir": {
					"value": "/tmp"
				},
				"catalina.home": {
					"value": "/tmp/tomcat.13823454205626436862.8080"
				},
				"java.version": {
					"value": "11.0.7"
				},
				"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.13823454205626436862.8080"
				},
				"java.library.path": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/jre/lib:/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib"
				},
				"java.vendor": {
					"value": "BellSoft"
				},
				"java.vm.info": {
					"value": "mixed mode"
				},
				"java.vm.version": {
					"value": "11.0.7+10-LTS"
				},
				"sun.io.unicode.encoding": {
					"value": "UnicodeLittle"
				},
				"java.class.version": {
					"value": "55.0"
				}
			}
		},
		{
			"name": "systemEnvironment",
			"properties": {
				"PATH": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/security-providers-configurer/bin:/layers/paketo-buildpacks_bellsoft-liberica/openssl-security-provider/bin:/layers/paketo-buildpacks_bellsoft-liberica/memory-calculator/bin:/layers/paketo-buildpacks_bellsoft-liberica/link-local-dns/bin:/layers/paketo-buildpacks_bellsoft-liberica/jre/bin:/layers/paketo-buildpacks_bellsoft-liberica/class-counter/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
					"origin": "System Environment Property \"PATH\""
				},
				"BOOT_DEMO_SERVICE_PORT": {
					"value": "80",
					"origin": "System Environment Property \"BOOT_DEMO_SERVICE_PORT\""
				},
				"KUBERNETES_PORT": {
					"value": "tcp://172.20.0.1:443",
					"origin": "System Environment Property \"KUBERNETES_PORT\""
				},
				"JAVA_HOME": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/jre",
					"origin": "System Environment Property \"JAVA_HOME\""
				},
				"JAVA_OPTS": {
					"value": " -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=2 -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=85939K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx450636K",
					"origin": "System Environment Property \"JAVA_OPTS\""
				},
				"KUBERNETES_SERVICE_HOST": {
					"value": "172.20.0.1",
					"origin": "System Environment Property \"KUBERNETES_SERVICE_HOST\""
				},
				"LD_LIBRARY_PATH": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/jre/lib",
					"origin": "System Environment Property \"LD_LIBRARY_PATH\""
				},
				"JAVA_SECURITY_PROPERTIES": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties",
					"origin": "System Environment Property \"JAVA_SECURITY_PROPERTIES\""
				},
				"BOOT_DEMO_PORT": {
					"value": "tcp://172.20.11.79:80",
					"origin": "System Environment Property \"BOOT_DEMO_PORT\""
				},
				"BOOT_DEMO_PORT_80_TCP": {
					"value": "tcp://172.20.11.79:80",
					"origin": "System Environment Property \"BOOT_DEMO_PORT_80_TCP\""
				},
				"PWD": {
					"value": "/workspace",
					"origin": "System Environment Property \"PWD\""
				},
				"BOOT_DEMO_SERVICE_HOST": {
					"value": "172.20.11.79",
					"origin": "System Environment Property \"BOOT_DEMO_SERVICE_HOST\""
				},
				"_": {
					"value": "/layers/paketo-buildpacks_bellsoft-liberica/jre/bin/java",
					"origin": "System Environment Property \"_\""
				},
				"KUBERNETES_PORT_443_TCP": {
					"value": "tcp://172.20.0.1:443",
					"origin": "System Environment Property \"KUBERNETES_PORT_443_TCP\""
				},
				"BOOT_DEMO_PORT_80_TCP_PROTO": {
					"value": "tcp",
					"origin": "System Environment Property \"BOOT_DEMO_PORT_80_TCP_PROTO\""
				},
				"KUBERNETES_PORT_443_TCP_ADDR": {
					"value": "172.20.0.1",
					"origin": "System Environment Property \"KUBERNETES_PORT_443_TCP_ADDR\""
				},
				"KUBERNETES_PORT_443_TCP_PROTO": {
					"value": "tcp",
					"origin": "System Environment Property \"KUBERNETES_PORT_443_TCP_PROTO\""
				},
				"CLASSPATH": {
					"value": "/workspace",
					"origin": "System Environment Property \"CLASSPATH\""
				},
				"KUBERNETES_SERVICE_PORT": {
					"value": "443",
					"origin": "System Environment Property \"KUBERNETES_SERVICE_PORT\""
				},
				"BOOT_DEMO_PORT_80_TCP_PORT": {
					"value": "80",
					"origin": "System Environment Property \"BOOT_DEMO_PORT_80_TCP_PORT\""
				},
				"HOSTNAME": {
					"value": "boot-demo-647b49ddcc-97zcm",
					"origin": "System Environment Property \"HOSTNAME\""
				},
				"BOOT_DEMO_PORT_80_TCP_ADDR": {
					"value": "172.20.11.79",
					"origin": "System Environment Property \"BOOT_DEMO_PORT_80_TCP_ADDR\""
				},
				"KUBERNETES_PORT_443_TCP_PORT": {
					"value": "443",
					"origin": "System Environment Property \"KUBERNETES_PORT_443_TCP_PORT\""
				},
				"KUBERNETES_SERVICE_PORT_HTTPS": {
					"value": "443",
					"origin": "System Environment Property \"KUBERNETES_SERVICE_PORT_HTTPS\""
				},
				"SHLVL": {
					"value": "1",
					"origin": "System Environment Property \"SHLVL\""
				},
				"HOME": {
					"value": "/home/cnb",
					"origin": "System Environment Property \"HOME\""
				},
				"MALLOC_ARENA_MAX": {
					"value": "2",
					"origin": "System Environment Property \"MALLOC_ARENA_MAX\""
				}
			}
		},
		{
			"name": "applicationConfig: [classpath:/application.properties]",
			"properties": {
				"management.endpoints.enabled-by-default": {
					"value": "true",
					"origin": "class path resource [application.properties]:1:41"
				},
				"management.endpoints.web.exposure.include": {
					"value": "*",
					"origin": "class path resource [application.properties]:2:43"
				}
			}
		}
	]
}
```

# まとめ＆考察
今までは以下のようにDockerfileを作成する必要があった。

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

https://spring.pleiades.io/guides/gs/spring-boot-docker/

これを作らなくていいのは確かに便利であるが、逆に言うと勝手に選定されてしまうため、商用で利用する場合は、そのような条件下で問題ないか確認する必要がある。
例えば、JVMの保守などが必要なエンタープライズ向けプロジェクトの場合は、あまり向いていないと考えられる。しかし、小規模でそのような細かいことに拘らないプロジェクトであれば、Dockerの知識があまり不要なため、採用する余地はあると考える。
勿論、作業省力化のため、CI/CDも事前にセットで作成しておくべきなのは言うまでもない。
## 参考
https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/gradle-plugin/reference/html/#build-image