micronaut-projects / micronaut-gradle-plugin

A Gradle Plugin for Micronaut
Apache License 2.0
66 stars 43 forks source link

Use Google's distroless containers for running the Graal native-image compiled application #94

Closed mikaelhg closed 3 years ago

mikaelhg commented 3 years ago

Use a better supported minimal distroless container from Google for running the Graal native-image built application, rather than the Alpine-based frolvlad/alpine-glibc.

Adding the parameter -H:+StaticExecutableWithDynamicLibC in the native-image invocation will build a "nearly static" binary, as described in oracle/graal#2589.

FROM oracle/graalvm-ce:20.3.0-java11 AS graalvm
RUN gu install native-image
WORKDIR /home/app
COPY build/layers/libs /home/app/libs
COPY build/layers/resources /home/app/resources
COPY build/layers/application.jar /home/app/application.jar
RUN native-image -H:Class=com.example.Application -H:Name=application \
      -H:+StaticExecutableWithDynamicLibC --no-fallback \
      -cp /home/app/libs/*.jar:/home/app/resources:/home/app/application.jar

FROM gcr.io/distroless/cc-debian10
COPY --from=graalvm /home/app/application /app/application
ENTRYPOINT ["/app/application"]
graemerocher commented 3 years ago

Note this is easy to do today without too much configuration:

dockerfileNative {
    baseImage = "gcr.io/distroless/cc-debian10"
}
nativeImage {
    args("-H:+StaticExecutableWithDynamicLibC")
}
ilopmar commented 3 years ago

We decided sometime ago that, as GraalVM default is to build dynamic native images, we will go the same way. In any case, we implemented an option that if users select a distroless base image, the plugin will automatically add the necessary -H:+StaticExecutableWithDynamicLibC flag.

So, the only thing you need to do to build a mostly-static native image is:

dockerfileNative {
    baseImage = "gcr.io/distroless/cc-debian10"
}
anandjaisy commented 1 month ago

@ilopmar @graemerocher setting the below configuration

tasks.named<io.micronaut.gradle.docker.NativeImageDockerfile>("optimizedDockerfileNative") {
    jdkVersion = "21"
    baseImage("gcr.io/distroless/static-debian12")
    args("-H:+StaticExecutableWithDynamicLibC")
    graalArch.set("aarch64")
}

Docker file generated is

FROM ghcr.io/graalvm/native-image-community:21-ol9 AS graalvm
WORKDIR /home/app
COPY --link layers/libs /home/app/libs
COPY --link layers/app /home/app/
RUN mkdir /home/app/config-dirs
RUN mkdir -p /home/app/config-dirs/generateResourcesConfigFile
RUN mkdir -p /home/app/config-dirs/com.fasterxml.jackson.core/jackson-databind/2.15.2
RUN mkdir -p /home/app/config-dirs/io.netty/netty-common/4.1.80.Final
RUN mkdir -p /home/app/config-dirs/io.grpc/grpc-netty/1.51.0
RUN mkdir -p /home/app/config-dirs/ch.qos.logback/logback-classic/1.4.9
RUN mkdir -p /home/app/config-dirs/org.postgresql/postgresql/42.3.4
RUN mkdir -p /home/app/config-dirs/com.zaxxer/HikariCP/5.0.1
COPY --link config-dirs/generateResourcesConfigFile /home/app/config-dirs/generateResourcesConfigFile
COPY --link config-dirs/com.fasterxml.jackson.core/jackson-databind/2.15.2 /home/app/config-dirs/com.fasterxml.jackson.core/jackson-databind/2.15.2
COPY --link config-dirs/io.netty/netty-common/4.1.80.Final /home/app/config-dirs/io.netty/netty-common/4.1.80.Final
COPY --link config-dirs/io.grpc/grpc-netty/1.51.0 /home/app/config-dirs/io.grpc/grpc-netty/1.51.0
COPY --link config-dirs/ch.qos.logback/logback-classic/1.4.9 /home/app/config-dirs/ch.qos.logback/logback-classic/1.4.9
COPY --link config-dirs/org.postgresql/postgresql/42.3.4 /home/app/config-dirs/org.postgresql/postgresql/42.3.4
COPY --link config-dirs/com.zaxxer/HikariCP/5.0.1 /home/app/config-dirs/com.zaxxer/HikariCP/5.0.1
RUN native-image --exclude-config .*/libs/netty-handler-4.1.111.Final.jar ^/META-INF/native-image/.* --exclude-config .*/libs/grpc-netty-1.64.0.jar ^/META-INF/native-image/.* --exclude-config .*/libs/netty-buffer-4.1.111.Final.jar ^/META-INF/native-image/.* --exclude-config .*/libs/netty-common-4.1.111.Final.jar ^/META-INF/native-image/.* --exclude-config .*/libs/netty-codec-http-4.1.111.Final.jar ^/META-INF/native-image/.* --exclude-config .*/libs/netty-transport-4.1.111.Final.jar ^/META-INF/native-image/.* --exclude-config .*/libs/netty-codec-http2-4.1.111.Final.jar ^/META-INF/native-image/.* -cp /home/app/libs/*.jar:/home/app/resources:/home/app/application.jar --no-fallback -o application -H:ConfigurationFileDirectories=/home/app/config-dirs/generateResourcesConfigFile,/home/app/config-dirs/com.fasterxml.jackson.core/jackson-databind/2.15.2,/home/app/config-dirs/io.netty/netty-codec-http/4.1.80.Final,/home/app/config-dirs/io.netty/netty-common/4.1.80.Final,/home/app/config-dirs/io.netty/netty-buffer/4.1.80.Final,/home/app/config-dirs/io.netty/netty-transport/4.1.80.Final,/home/app/config-dirs/io.netty/netty-handler/4.1.80.Final,/home/app/config-dirs/io.netty/netty-codec-http2/4.1.80.Final,/home/app/config-dirs/io.grpc/grpc-netty/1.51.0,/home/app/config-dirs/ch.qos.logback/logback-classic/1.4.9,/home/app/config-dirs/org.postgresql/postgresql/42.3.4,/home/app/config-dirs/com.zaxxer/HikariCP/5.0.1 fete.bird.Assessment -H:+StaticExecutableWithDynamicLibC
FROM gcr.io/distroless/static-debian12

COPY --link --from=graalvm /home/app/application /app/application
ENTRYPOINT ["/app/application", "-H:+StaticExecutableWithDynamicLibC"]

How do we generated config-dirs/** and layers/** directories, while using the docker-compose pointing to this docker file

version: '3.8'

services:
  assessment:
    build:
      context: ./assessment/build/docker/native-optimized
      dockerfile: DockerfileNative
    container_name: assessment
    ports:
      - 8082:8082
// Other service