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で取得できる環境情報

{
    "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を作成する必要があった。

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

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

参考