From bdaeeb68249a57bae94653bf54bf4b71cb4b483b Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Thu, 24 Oct 2024 17:04:14 -0400 Subject: [PATCH 1/8] Convert all container builds to multi-stage. Add JVM containers for comparison. --- tiny-java-containers/README.md | 186 +++++++----------- tiny-java-containers/clean.sh | 1 - tiny-java-containers/helloworld/Dockerfile | 28 ++- tiny-java-containers/helloworld/build.sh | 19 +- tiny-java-containers/helloworld/clean.sh | 3 - .../jwebserver/Dockerfile.alpine.static | 10 +- .../Dockerfile.distroless-base.mostly | 10 +- .../Dockerfile.distroless-java-base.dynamic | 10 +- .../Dockerfile.distroless-java-base.jlink | 20 +- .../Dockerfile.distroless-static.static | 10 +- .../jwebserver/Dockerfile.jvm-debian-slim | 11 ++ .../jwebserver/Dockerfile.jvm-distroless-java | 4 + .../jwebserver/Dockerfile.jvm-eclipse-temurin | 4 + .../jwebserver/Dockerfile.scratch.static | 10 +- .../jwebserver/Dockerfile.scratch.static-upx | 23 ++- tiny-java-containers/jwebserver/build-all.sh | 5 +- .../jwebserver/build-dynamic.sh | 3 - .../jwebserver/build-jlink.sh | 12 -- tiny-java-containers/jwebserver/build-jvm.sh | 10 + .../jwebserver/build-mostly.sh | 2 - .../jwebserver/build-static.sh | 12 +- tiny-java-containers/jwebserver/clean.sh | 5 +- tiny-java-containers/setup-musl.sh | 34 ---- tiny-java-containers/setup-upx.sh | 13 -- 24 files changed, 211 insertions(+), 234 deletions(-) create mode 100644 tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim create mode 100644 tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java create mode 100644 tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin create mode 100755 tiny-java-containers/jwebserver/build-jvm.sh delete mode 100755 tiny-java-containers/setup-musl.sh delete mode 100755 tiny-java-containers/setup-upx.sh diff --git a/tiny-java-containers/README.md b/tiny-java-containers/README.md index 70062ead1..a2ab0dc4e 100644 --- a/tiny-java-containers/README.md +++ b/tiny-java-containers/README.md @@ -1,6 +1,6 @@ # Tiny Java Containers -This example shows how a simple Java application and a simple web +This demo shows how a simple Java application and a simple web server can be compiled to produce very small Docker container images. The smallest container images contains just an executable. But since there's @@ -13,7 +13,7 @@ To support static linking of `libc`, GraalVM Native Image supports using the implementation. You can watch a [Devoxx 2022](https://devoxx.be/) session that walks through -this example on YouTube. +an earlier version of this example on YouTube. [![A 1.5MB Java Container App](images/youtube.png)](https://youtu.be/6wYrAtngIVo) @@ -22,119 +22,70 @@ App](images/youtube.png)](https://youtu.be/6wYrAtngIVo) * x86 Linux (but the few binary dependencies could easily be changed for aarch64) * Docker installed and running. It should work fine with [podman](https://podman.io/) but it has not been tested. -* [GraalVM for JDK 21](https://www.graalvm.org/downloads/) -> We recommend Oracle GraalVM for the best experience. It is licensed under the [GraalVM Free Terms and Conditions (GFTC)](https://www.oracle.com/downloads/licenses/graal-free-license.html) license, which permits use by any user including commercial and production use. -GraalVM Community Edition for JDK 21 works too, but Native Image generated executables sizes will differ. - -> These instructions have only been tested on Linux x64. +> NOTE: These instructions have only been tested on Linux x64. ## Setup -You need the following zlib packages installed: -* zlib.x86_64 -* zlib-devel.x86_64 -* zlib-static.x86_64 - -On Oracle Linux, you can install with: -```sh -sudo yum install -y zlib.x86_64 -sudo yum install -y zlib-devel.x86_64 -sudo yum install -y zlib-static.x86_64 -``` - -Clone this Git repo and in your Linux shell type the following to download and -configure the `musl` toolchain. - -![](images/keyboard.jpg) `./setup-musl.sh` - -Download [upx](https://upx.github.io/): - -![](images/keyboard.jpg) `./setup-upx.sh` +Clone this Git repo. Everything runs in Docker so no need to install anything +on your machine. ## Hello World -With the `musl` toolchain installed, cd in to the `helloworld` folder. +Let's start with a simple Hello World example. + +CD into the `helloworld` folder. ![](images/keyboard.jpg) `cd helloworld` -Using the `build.sh` script, compile a simple single Java class Hello World -application with `javac`, compile the generated .class file into a fully -statically linked native Linux executable named `hello`, compress the executable -with [upx](https://upx.github.io/) to create the executable `hello.upx`, and -package the compressed static `hello.upx` executable into a `scratch` -Docker container image: +Use the `build.sh` script to run a Docker build that: +1. compiles a simple single Java class Hello World application with `javac` +2. compiles the generated .class file with GraalVM Native Image into a fully +statically linked native Linux executable named `hello` +3. compresses the executable with [upx](https://upx.github.io/) to create the +executable `hello.upx` +4. packages the compressed static `hello.upx` executable into a `scratch` Docker +container image -![](images/keyboard.jpg) `./build.sh` +In a terminal, run: -You'll see two executables were built: - -![](images/keyboard.jpg) `ls -lh hello*` +![](images/keyboard.jpg) `./build.sh` ### Native Executables -Running either of the `hello` executables you can see they are functionally -equivalent. They just print "Hello World". But there are a few points worth -noting: - -1. The executable generated by GraalVM Native Image using the - `--static --libc=musl` options is a fully self-contained executable which can be - confirmed by examining it with `ldd`: - - ![](images/keyboard.jpg) `ldd hello` - - should result in: - - ```shell - not a dynamic executable - ``` - - This means that it does not rely on any libraries in the host operating system - environment making it easier to package in a variety of Docker container images. - - Unfortunately `upx` compression renders `ldd` unable to list the shared - libraries of an executable, but since you compressed the statically linked - executable, you can be confident it is also statically linked. - -2. Both executables are the result of compiling a Java bytecode application into - native machine code. The uncompressed executable is only ~6.3MB! There's no - JVM, no JARs, no JIT compiler and none of the overhead it imposes. Both - start extremely fast as there is minimal startup cost. - -3. The `upx` compressed executable is over 70% smaller, 1.7MB vs. 6.3MB! With - `upx` the application self-extracts quickly but does incur a cost of about - 100ms for decompression. See this blog for a deep dive on [GraalVM Native - Image and +1. The `hello` executable generated by GraalVM Native Image in the Dockerfile + using the `--static --libc=musl` options is a fully self-contained + executable. This means that it does not rely on any libraries in the host + operating system environment. This makes it easier to package in a variety + of Docker container images. + +2. You can see in the output of the Dockerfile build that `ls -lh` reports the + `hello` executable is ~4.9MB. There's no JVM, no JARs, no JIT compiler and + none of the overhead it imposes. It starts extremely fast as there is minimal + startup cost. + +3. The `upx` compressed `hello.upx` executable is over 70% smaller, 1.3MB vs. + 4.9MB! A `upx` compressed application self-extracts quickly but does incur a + cost of about 100ms for decompression. See this blog for a deep dive on + [GraalVM Native Image and UPX](https://medium.com/graalvm/compressed-graalvm-native-images-4d233766a214). ### Container Images -The size of the `scratch`-based container image is slightly more than the `hello.upx` -executable. +The size of the `scratch`-based container image is about the same size as the `hello.upx` +executable since it adds little overhead. ![](images/keyboard.jpg) `docker images hello` ```shell REPOSITORY TAG IMAGE ID CREATED SIZE -hello upx 4d122bd39a8a About a minute ago 1.78 MB +hello upx b69a5d79e8dc 1 second ago 1.3MB ``` This is a tiny container image and yet it contains a fully functional and -deployable (although fairly useless 😉) application. The Dockerfile that -generated it simply copies the executable into the container image and sets the -executable as the `ENTRYPOINT`. - -A better way to build these images is with a multi-stage build, but to keep the -focus on the final result, build on a host machine and copy the binary into -the container image. E.g., - -```docker -FROM scratch -COPY hello.upx / -ENTRYPOINT ["/hello.upx"] -``` +deployable (although fairly useless 😉) application. -Running the container image is straight forward: +Running the executable in the container image is straight forward: ![](images/keyboard.jpg) `docker run --rm hello:upx` @@ -153,7 +104,7 @@ introduced in JDK 18 and build a containerized executable that serves up web pages. How small can a containerized Java web server be? Would you believe a measly -5.5MB? Let's see. +4.4MB? Let's see. Let's move from the `helloworld` folder over to the `jwebserver` folder. @@ -171,30 +122,29 @@ custome runtime image for comparison. ![](images/keyboard.jpg) `./build-all.sh` -The various Dockerfiles simply copy the executable or `jlink` generated custom -runtime image folder into the container image along with an `index.html` file to -serve, and set the `ENTRYPOINT`. E.g., +The various Dockerfiles simply copy the compiled executable or `jlink` generated +custom runtime image folder into the deployment container image along with an +`index.html` file to serve, and set the `ENTRYPOINT`. -```docker -FROM scratch -COPY jwebserver.static / -COPY index.html /web/index.html -ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] -``` +The Distroless Java, Eclipse Temurin, and Debian container images include a full +JDK, which includes jwebserver. -When complete you can see the sizes of the various versions: +When complete you can see the sizes of the various variants: ![](images/keyboard.jpg) `$ docker images jwebserver` ```shell REPOSITORY TAG IMAGE ID CREATED SIZE -jwebserver distroless-java-base.jlink 414d84f8b7c7 22 minutes ago 132 MB -jwebserver scratch.static-upx 47aabdd14c04 22 minutes ago 4.71 MB -jwebserver alpine.static 783ab3a60248 22 minutes ago 23.4 MB -jwebserver distroless-static.static c894f14d4068 22 minutes ago 18.7 MB -jwebserver scratch.static 034cfbdf3577 22 minutes ago 15.7 MB -jwebserver distroless-base.mostly e99811e574d3 22 minutes ago 37.6 MB -jwebserver distroless-java-base.dynamic 72a210e3c705 23 minutes ago 50.6 MB +jwebserver distroless-java de7f7efb6df4 4 minutes ago 192MB +jwebserver temurin 643203bf8168 4 minutes ago 451MB +jwebserver debian fa5bfa4b2e5e 4 minutes ago 932MB +jwebserver distroless-java-base.jlink c3113c2400ea 5 minutes ago 122MB +jwebserver scratch.static-upx 75b3bb3249f3 5 minutes ago 4.12MB +jwebserver alpine.static 178081760470 6 minutes ago 21.6MB +jwebserver distroless-static.static 84053f6323c1 6 minutes ago 15.8MB +jwebserver scratch.static 98061f48037c 6 minutes ago 13.8MB +jwebserver distroless-base.mostly b33fc99fbe2a 7 minutes ago 34.3MB +jwebserver distroless-java-base.dynamic 1aceeabbb329 7 minutes ago 46.9MB ``` Sorting by size, it's clear that the fully statically linked GraalVM Native @@ -204,15 +154,19 @@ of the `jlink` version (`distroless-java-base.jlink`) running on the JVM. | Base Image | App Version | Size (MB) | | -------------------- | ---------------------------------- | --------- | -| Distroless Java Base | jlink | 132.00 | -| Distroless Java Base | native *dynamic* linked | 50.60 | -| Distroless Base | native *mostly* static linked | 37.60 | -| Alpine | native *fully* static linked | 23.40 | -| Distroless Static | native *fully* static linked | 18.70 | -| Scratch | native *fully* static linked | 15.70 | -| Scratch | *compressed* native *fully* static | 4.71 | - -Running a container image is straight forward, just remember to map the ports, e.g.: +| Debian Slim + JDK | jwebserver included in the JDK | 932.00 | +| Eclipse Temurin | jwebserver included in the JDK | 451.00 | +| Distroless Java | jwebserver included in the JDK | 192.00 | +| Distroless Java Base | jlink | 122.00 | +| Distroless Java Base | native *dynamic* linked | 46.90 | +| Distroless Base | native *mostly* static linked | 34.30 | +| Alpine | native *fully* static linked | 21.60 | +| Distroless Static | native *fully* static linked | 15.80 | +| Scratch | native *fully* static linked | 13.80 | +| Scratch | *compressed* native *fully* static | 4.12 | + +Running a container image is once again straight forward, just remember to map +the server port, e.g.: ![](images/keyboard.jpg) `docker run --rm -p8000:8000 jwebserver:scratch.static` @@ -225,8 +179,8 @@ the index.html file. ## Wrapping Up -A fully functional, albeit minimal, Java "microservice" was compiled -into a native Linux executable and packaged into Distroless, Alpine, and +A fully functional, albeit minimal, Java "microservice" was compiled into a +native Linux executable and packaged into Distroless, Alpine, and `scratch`-based container images thanks to GraalVM Native Image's support for various linking options including fully static linking with the `musl` libc. diff --git a/tiny-java-containers/clean.sh b/tiny-java-containers/clean.sh index b12d90e89..1c4306820 100755 --- a/tiny-java-containers/clean.sh +++ b/tiny-java-containers/clean.sh @@ -2,7 +2,6 @@ set +e -rm -rf x86_64-linux-musl-native zlib-* cd helloworld ./clean.sh || true cd ../jwebserver diff --git a/tiny-java-containers/helloworld/Dockerfile b/tiny-java-containers/helloworld/Dockerfile index 7cb1ee95e..cafd6340f 100644 --- a/tiny-java-containers/helloworld/Dockerfile +++ b/tiny-java-containers/helloworld/Dockerfile @@ -1,3 +1,29 @@ + +# Build in a container with Oracle GraalVM Native Image and MUSL +FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild +WORKDIR /build +# Install UPX +ARG UPX_VERSION=4.2.2 +ARG UPX_ARCHIVE=upx-${UPX_VERSION}-amd64_linux.tar.xz +RUN microdnf -y install wget xz && \ + wget -q https://github.com/upx/upx/releases/download/v${UPX_VERSION}/${UPX_ARCHIVE} && \ + tar -xJf ${UPX_ARCHIVE} && \ + rm -rf ${UPX_ARCHIVE} && \ + mv upx-${UPX_VERSION}-amd64_linux/upx . && \ + rm -rf upx-${UPX_VERSION}-amd64_linux + + # Compile the Hello class to Java bytecode +COPY Hello.java Hello.java +RUN javac Hello.java +# Build a native executable with native-image +RUN native-image -Os --static --libc=musl Hello -o hello +RUN ls -lh hello + +# Compress the executable with UPX +RUN ./upx --lzma --best -o hello.upx hello +RUN ls -lh hello.upx + +# Copy the compressed executable into a scratch container FROM scratch -COPY hello.upx / +COPY --from=nativebuild /build/hello.upx /hello.upx ENTRYPOINT ["/hello.upx"] diff --git a/tiny-java-containers/helloworld/build.sh b/tiny-java-containers/helloworld/build.sh index bdf27515e..4496a4dba 100755 --- a/tiny-java-containers/helloworld/build.sh +++ b/tiny-java-containers/helloworld/build.sh @@ -1,20 +1,7 @@ #!/bin/sh -set -e - -TOOLCHAIN_DIR=`pwd`/../x86_64-linux-musl-native -CC=${TOOLCHAIN_DIR}/bin/gcc -PATH=${TOOLCHAIN_DIR}/bin:${PATH} - -# Compile Java source file -javac Hello.java - -# Compile Java bytecodes into a fully statically linked executable -native-image -Ob --static --libc=musl -o hello Hello -rm -rf *.txt - -# Create a compressed version of the executable -../upx --lzma --best hello -o hello.upx +set +e # Package the compressed executable in a simple scratch container image -docker build . -t hello:upx \ No newline at end of file +docker build . -t hello:upx +docker images hello \ No newline at end of file diff --git a/tiny-java-containers/helloworld/clean.sh b/tiny-java-containers/helloworld/clean.sh index 67c85f9bb..d0a994aaf 100755 --- a/tiny-java-containers/helloworld/clean.sh +++ b/tiny-java-containers/helloworld/clean.sh @@ -2,7 +2,4 @@ set +e -rm -rf hello hello.upx -rm -rf *.txt -rm -rf *.class docker images -q hello | awk '{print($1)}' | xargs docker rmi || true diff --git a/tiny-java-containers/jwebserver/Dockerfile.alpine.static b/tiny-java-containers/jwebserver/Dockerfile.alpine.static index 531014b67..1ddf41c8e 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.alpine.static +++ b/tiny-java-containers/jwebserver/Dockerfile.alpine.static @@ -1,5 +1,11 @@ +FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild +WORKDIR /build +# Build a statically linked native executable optimizing for size with `-Os` +RUN native-image -Os --static --libc=musl -m jdk.httpserver -o jwebserver.static +RUN ls -lh jwebserver.static + FROM alpine:3 -COPY jwebserver.static / +COPY --from=nativebuild /build/jwebserver.static / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly b/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly index 6eafde0f3..0c6082592 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly @@ -1,5 +1,11 @@ +FROM container-registry.oracle.com/graalvm/native-image:23 AS nativebuild +WORKDIR /build +# Build a native executable optimizing for size with `-Os` +RUN native-image --static-nolibc -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.mostly +RUN ls -lh jwebserver.mostly + FROM gcr.io/distroless/base-debian12 -COPY jwebserver.mostly / +COPY --from=nativebuild /build/jwebserver.mostly / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.mostly", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.mostly", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic index 3bd4fd105..25107158d 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic @@ -1,5 +1,11 @@ +FROM container-registry.oracle.com/graalvm/native-image:23 AS nativebuild +WORKDIR /build +# Build a dynamically linked native executable optimizing for size with `-Os` +RUN native-image -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.dynamic +RUN ls -lh jwebserver.dynamic + FROM gcr.io/distroless/java-base-debian12 -COPY jwebserver.dynamic / +COPY --from=nativebuild /build/jwebserver.dynamic / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.dynamic", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.dynamic", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink index fe737c7c6..20f71e06f 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink @@ -1,5 +1,21 @@ +FROM container-registry.oracle.com/graalvm/jdk:23 AS build +RUN microdnf install -y binutils +WORKDIR /build +# Build a runtime image optimized for size +RUN jlink \ + --module-path ${JAVA_HOME}/jmods \ + --add-modules jdk.httpserver \ + --verbose \ + --strip-debug \ + --compress zip-9 \ + --no-header-files \ + --no-man-pages \ + --strip-java-debug-attributes \ + --output jwebserver-jlink +RUN du -h jwebserver-jlink + FROM gcr.io/distroless/java-base-debian12 -COPY jwebserver-jlink /usr/lib/java +COPY --from=build /build/jwebserver-jlink /usr/lib/java COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/usr/lib/java/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/usr/lib/java/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static b/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static index d36c12ac1..47e5630ef 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static @@ -1,5 +1,11 @@ +FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild +WORKDIR /build +# Build a statically linked native executable optimizing for size with `-Os` +RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN ls -lh jwebserver.static + FROM gcr.io/distroless/static-debian12 -COPY jwebserver.static / +COPY --from=nativebuild /build/jwebserver.static / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim b/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim new file mode 100644 index 000000000..351d93726 --- /dev/null +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim @@ -0,0 +1,11 @@ +FROM debian:12-slim +WORKDIR /web +RUN apt-get update && \ + apt-get install -y wget && \ + apt-get clean && \ + wget -q https://download.oracle.com/graalvm/23/archive/graalvm-jdk-23_linux-x64_bin.tar.gz -O graalvm.tar.gz && \ + tar -xf graalvm.tar.gz && \ + rm -f graalvm.tar.gz +COPY index.html /web/index.html +EXPOSE 8000 +ENTRYPOINT ["/web/graalvm-jdk-23+37.1/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java b/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java new file mode 100644 index 000000000..b0c182245 --- /dev/null +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java @@ -0,0 +1,4 @@ +FROM gcr.io/distroless/java21-debian12 +COPY index.html /web/index.html +EXPOSE 8000 +ENTRYPOINT ["/opt/java/openjdk/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin b/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin new file mode 100644 index 000000000..84b427a13 --- /dev/null +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin @@ -0,0 +1,4 @@ +FROM eclipse-temurin:23 +COPY index.html /web/index.html +EXPOSE 8000 +ENTRYPOINT ["/opt/java/openjdk/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.scratch.static b/tiny-java-containers/jwebserver/Dockerfile.scratch.static index 579fabec9..02545ab17 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.scratch.static +++ b/tiny-java-containers/jwebserver/Dockerfile.scratch.static @@ -1,5 +1,11 @@ +FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild +WORKDIR /build +# Build a statically linked native executable optimizing for size with `-Os` +RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN ls -lh jwebserver.static + FROM scratch -COPY jwebserver.static / +COPY --from=nativebuild /build/jwebserver.static / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.static", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx b/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx index 23ca47bb8..31fe91cd7 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx +++ b/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx @@ -1,5 +1,24 @@ +FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild +WORKDIR /build + +# Build a statically linked native executable optimizing for size with `-Os` +RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN ls -lh jwebserver.static + +# Install and use UPX +ARG UPX_VERSION=4.2.2 +ARG UPX_ARCHIVE=upx-${UPX_VERSION}-amd64_linux.tar.xz +RUN microdnf -y install wget xz && \ + wget -q https://github.com/upx/upx/releases/download/v${UPX_VERSION}/${UPX_ARCHIVE} && \ + tar -xJf ${UPX_ARCHIVE} && \ + rm -rf ${UPX_ARCHIVE} && \ + mv upx-${UPX_VERSION}-amd64_linux/upx . && \ + rm -rf upx-${UPX_VERSION}-amd64_linux +RUN ./upx --lzma --best -o jwebserver.static-upx jwebserver.static +RUN ls -lh jwebserver.static-upx + FROM scratch -COPY jwebserver.static-upx / +COPY --from=nativebuild /build/jwebserver.static-upx / COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/jwebserver.static-upx", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/jwebserver.static-upx", "-b", "0.0.0.0", "-d", "/web"] diff --git a/tiny-java-containers/jwebserver/build-all.sh b/tiny-java-containers/jwebserver/build-all.sh index 1d80247f1..40f0b881b 100755 --- a/tiny-java-containers/jwebserver/build-all.sh +++ b/tiny-java-containers/jwebserver/build-all.sh @@ -4,10 +4,7 @@ ./build-mostly.sh ./build-static.sh ./build-jlink.sh -rm *.txt - -echo "Generated Executables" -ls -lh jwebserver* +./build-jvm.sh echo "Generated Docker Container Images" docker images jwebserver diff --git a/tiny-java-containers/jwebserver/build-dynamic.sh b/tiny-java-containers/jwebserver/build-dynamic.sh index 730a9bd0d..8e13e93f8 100755 --- a/tiny-java-containers/jwebserver/build-dynamic.sh +++ b/tiny-java-containers/jwebserver/build-dynamic.sh @@ -1,8 +1,5 @@ #!/bin/sh -# compile with fully dynamically linked shared libraries -native-image -Ob -m jdk.httpserver -o jwebserver.dynamic - # Distroless Java Base-provides glibc and other libraries needed by the JDK docker build . -f Dockerfile.distroless-java-base.dynamic -t jwebserver:distroless-java-base.dynamic diff --git a/tiny-java-containers/jwebserver/build-jlink.sh b/tiny-java-containers/jwebserver/build-jlink.sh index bfc40b675..5b6f20bda 100755 --- a/tiny-java-containers/jwebserver/build-jlink.sh +++ b/tiny-java-containers/jwebserver/build-jlink.sh @@ -1,16 +1,4 @@ #!/bin/sh -rm -rf jwebserver-jlink -jlink \ - --module-path ${JAVA_HOME}/jmods \ - --add-modules jdk.httpserver \ - --verbose \ - --strip-debug \ - --compress zip-9 \ - --no-header-files \ - --no-man-pages \ - --strip-java-debug-attributes \ - --output jwebserver-jlink - # Distroless Java Base-provides glibc and other libraries needed by the JDK docker build . -f Dockerfile.distroless-java-base.jlink -t jwebserver:distroless-java-base.jlink diff --git a/tiny-java-containers/jwebserver/build-jvm.sh b/tiny-java-containers/jwebserver/build-jvm.sh new file mode 100755 index 000000000..f8df4cf8a --- /dev/null +++ b/tiny-java-containers/jwebserver/build-jvm.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Debian Slim image with JDK +docker build . -f Dockerfile.jvm-debian-slim -t jwebserver:debian + +# Eclipse Temuring JDK Image +docker build . -f Dockerfile.jvm-eclipse-temurin -t jwebserver:temurin + +# Distoless Java 21 (Debian) +docker build . -f Dockerfile.jvm-distroless-java -t jwebserver:distroless-java diff --git a/tiny-java-containers/jwebserver/build-mostly.sh b/tiny-java-containers/jwebserver/build-mostly.sh index 2a0db4092..2120b4ae6 100755 --- a/tiny-java-containers/jwebserver/build-mostly.sh +++ b/tiny-java-containers/jwebserver/build-mostly.sh @@ -1,6 +1,4 @@ #!/bin/sh -native-image -Ob -H:+UnlockExperimentalVMOptions -H:+StaticExecutableWithDynamicLibC -m jdk.httpserver -o jwebserver.mostly - # Distroless Base (provides glibc) docker build . -f Dockerfile.distroless-base.mostly -t jwebserver:distroless-base.mostly diff --git a/tiny-java-containers/jwebserver/build-static.sh b/tiny-java-containers/jwebserver/build-static.sh index 34b92a47a..f73a5ec54 100755 --- a/tiny-java-containers/jwebserver/build-static.sh +++ b/tiny-java-containers/jwebserver/build-static.sh @@ -1,11 +1,5 @@ #!/bin/sh -TOOLCHAIN_DIR=`pwd`/../x86_64-linux-musl-native -CC=${TOOLCHAIN_DIR}/bin/gcc -PATH=${TOOLCHAIN_DIR}/bin:${PATH} - -native-image -Ob --static --libc=musl -m jdk.httpserver -o jwebserver.static - # Scratch-nothing docker build . -f Dockerfile.scratch.static -t jwebserver:scratch.static @@ -15,9 +9,5 @@ docker build . -f Dockerfile.distroless-static.static -t jwebserver:distroless-s # Alpine-no glibc docker build . -f Dockerfile.alpine.static -t jwebserver:alpine.static -# Compress with UPX -rm -f jwebserver.static-upx -../upx --lzma --best -o jwebserver.static-upx jwebserver.static - # Scratch--fully static and compressed -docker build . -f Dockerfile.scratch.static-upx -t jwebserver:scratch.static-upx \ No newline at end of file +docker build . -f Dockerfile.scratch.static-upx -t jwebserver:scratch.static-upx diff --git a/tiny-java-containers/jwebserver/clean.sh b/tiny-java-containers/jwebserver/clean.sh index da4bd3c0d..0ba5ac92f 100755 --- a/tiny-java-containers/jwebserver/clean.sh +++ b/tiny-java-containers/jwebserver/clean.sh @@ -2,7 +2,4 @@ set +e -rm -rf jwebserver-jlink/ -rm jwebserver.dynamic jwebserver.mostly jwebserver.static jwebserver.static-upx -rm -rf svm*.md -docker images jwebserver -q | grep -v TAG | awk '{print($1)}' | xargs docker rmi \ No newline at end of file +docker images jwebserver -q | grep -v TAG | awk '{print($1)}' | xargs docker rmi -f \ No newline at end of file diff --git a/tiny-java-containers/setup-musl.sh b/tiny-java-containers/setup-musl.sh deleted file mode 100755 index 8b2dd5d9d..000000000 --- a/tiny-java-containers/setup-musl.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Specify an installation directory for musl: -export MUSL_HOME=$PWD/musl-toolchain - -# Download musl and zlib sources: -curl -O https://musl.libc.org/releases/musl-1.2.4.tar.gz -curl -O https://zlib.net/fossils/zlib-1.2.13.tar.gz - -# Build musl from source -tar -xzf musl-1.2.4.tar.gz -rm musl-1.2.4.tar.gz -pushd musl-1.2.4 -./configure --prefix=$MUSL_HOME --static -make -make install -popd - -# Install a symlink for use by native-image -ln -s $MUSL_HOME/bin/musl-gcc $MUSL_HOME/bin/x86_64-linux-musl-gcc - -# Extend the system path and confirm that musl is available by printing its version -export PATH="$MUSL_HOME/bin:$PATH" -x86_64-linux-musl-gcc --version - -# Build zlib with musl from source and install into the MUSL_HOME directory -tar -xzvf zlib-1.2.13.tar.gz -rm zlib-1.2.13.tar.gz -pushd zlib-1.2.13 -CC=musl-gcc ./configure --prefix=$MUSL_HOME --static -make -make install -popd \ No newline at end of file diff --git a/tiny-java-containers/setup-upx.sh b/tiny-java-containers/setup-upx.sh deleted file mode 100755 index 04d93d1c8..000000000 --- a/tiny-java-containers/setup-upx.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -UPX_VERSION=4.2.2 -UPX_ARCHIVE=upx-${UPX_VERSION}-amd64_linux.tar.xz - -wget -q https://github.com/upx/upx/releases/download/v${UPX_VERSION}/${UPX_ARCHIVE} -tar -xJf ${UPX_ARCHIVE} -rm -rf ${UPX_ARCHIVE} -mv upx-${UPX_VERSION}-amd64_linux/upx . -rm -rf upx-${UPX_VERSION}-amd64_linux - From 3a5626534f7691cb7b786f51938e5d97d980e46d Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Thu, 24 Oct 2024 17:16:11 -0400 Subject: [PATCH 2/8] github actions --- .github/workflows/tiny-java-containers.yml | 45 +++++++++++++++------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tiny-java-containers.yml b/.github/workflows/tiny-java-containers.yml index 63565699f..362557733 100644 --- a/.github/workflows/tiny-java-containers.yml +++ b/.github/workflows/tiny-java-containers.yml @@ -23,24 +23,12 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} - name: Run 'tiny-java-containers' run: | - cd tiny-java-containers sleep_period=5 - # - # Setup musl toolchain - # - ./setup-musl.sh - export PATH="$PWD/musl-toolchain/bin:$PATH" - # - # Download upx - # - ./setup-upx.sh - # + cd tiny-java-containers # Hello World # cd helloworld ./build.sh - ./hello - ./hello.upx docker run --rm hello:upx cd .. # @@ -64,9 +52,12 @@ jobs: curl "http://localhost:8000" docker stop $container_id # - # Static Scratch + # Static # ./build-static.sh + # + # Static Scratch + # container_id=$(docker run -d --rm -p8000:8000 jwebserver:scratch.static) sleep $sleep_period curl "http://localhost:8000" @@ -100,3 +91,29 @@ jobs: sleep $sleep_period curl "http://localhost:8000" docker stop $container_id + # + # JDK Build + # + ./build-jvm.sh + # + # Debian JDK + # + container_id=$(docker run -d --rm -p8000:8000 jwebserver:debian) + sleep $sleep_period + curl "http://localhost:8000" + docker stop $container_id + # + # Eclipse Temurin Static + # + container_id=$(docker run -d --rm -p8000:8000 jwebserver:temurin) + sleep $sleep_period + curl "http://localhost:8000" + docker stop $container_id + # + # Distroless Java + # + ./build-jlink.sh + container_id=$(docker run -d --rm -p8000:8000 jwebserver:distroless-java) + sleep $sleep_period + curl "http://localhost:8000" + docker stop $container_id \ No newline at end of file From 862a2355f6c715044ae2336e1b11f6ae6d4158e6 Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Fri, 25 Oct 2024 14:14:36 -0400 Subject: [PATCH 3/8] java path in JVM images --- tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim | 2 +- tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java | 2 +- tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim b/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim index 351d93726..644290b08 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-debian-slim @@ -8,4 +8,4 @@ RUN apt-get update && \ rm -f graalvm.tar.gz COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/web/graalvm-jdk-23+37.1/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["/web/graalvm-jdk-23+37.1/bin/java", "-m", "jdk.httpserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java b/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java index b0c182245..b0179e0d2 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-distroless-java @@ -1,4 +1,4 @@ FROM gcr.io/distroless/java21-debian12 COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/opt/java/openjdk/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file +ENTRYPOINT ["java", "-m", "jdk.httpserver", "-b", "0.0.0.0", "-d", "/web"] \ No newline at end of file diff --git a/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin b/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin index 84b427a13..879f0f264 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin +++ b/tiny-java-containers/jwebserver/Dockerfile.jvm-eclipse-temurin @@ -1,4 +1,4 @@ FROM eclipse-temurin:23 COPY index.html /web/index.html EXPOSE 8000 -ENTRYPOINT ["/opt/java/openjdk/bin/jwebserver", "-b", "0.0.0.0", "-d", "/web"] +ENTRYPOINT ["java", "-m", "jdk.httpserver", "-b", "0.0.0.0", "-d", "/web"] From 0ea8bf5d1206b4ffccfbdc1b6ac02591d4d959df Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Mon, 28 Oct 2024 12:43:23 -0400 Subject: [PATCH 4/8] Update tiny-java-containers/README.md Co-authored-by: Olga Gupalo --- tiny-java-containers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-java-containers/README.md b/tiny-java-containers/README.md index a2ab0dc4e..e99813bd4 100644 --- a/tiny-java-containers/README.md +++ b/tiny-java-containers/README.md @@ -27,7 +27,7 @@ App](images/youtube.png)](https://youtu.be/6wYrAtngIVo) ## Setup -Clone this Git repo. Everything runs in Docker so no need to install anything +Clone this Git repo. Everything runs in Docker so no need to install anything on your machine. ## Hello World From 9df3379a9727ce1f1eef7904b3d77f4858926057 Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Mon, 28 Oct 2024 12:43:32 -0400 Subject: [PATCH 5/8] Update tiny-java-containers/README.md Co-authored-by: Olga Gupalo --- tiny-java-containers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-java-containers/README.md b/tiny-java-containers/README.md index e99813bd4..0110077c0 100644 --- a/tiny-java-containers/README.md +++ b/tiny-java-containers/README.md @@ -34,7 +34,7 @@ on your machine. Let's start with a simple Hello World example. -CD into the `helloworld` folder. +Change the directory to `helloworld`. ![](images/keyboard.jpg) `cd helloworld` From b2eae6d999430f9ee0e6a7db5c43c0f716f06624 Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Mon, 28 Oct 2024 12:43:38 -0400 Subject: [PATCH 6/8] Update tiny-java-containers/README.md Co-authored-by: Olga Gupalo --- tiny-java-containers/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-java-containers/README.md b/tiny-java-containers/README.md index 0110077c0..8339f2eb0 100644 --- a/tiny-java-containers/README.md +++ b/tiny-java-containers/README.md @@ -56,7 +56,7 @@ In a terminal, run: 1. The `hello` executable generated by GraalVM Native Image in the Dockerfile using the `--static --libc=musl` options is a fully self-contained executable. This means that it does not rely on any libraries in the host - operating system environment. This makes it easier to package in a variety + operating system environment. This makes it easier to package in a variety of container images. of Docker container images. 2. You can see in the output of the Dockerfile build that `ls -lh` reports the From 1e265408a7f51685f6e8e67e01588efa2aaf2e33 Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Mon, 28 Oct 2024 12:43:46 -0400 Subject: [PATCH 7/8] Update tiny-java-containers/helloworld/Dockerfile Co-authored-by: Olga Gupalo --- tiny-java-containers/helloworld/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny-java-containers/helloworld/Dockerfile b/tiny-java-containers/helloworld/Dockerfile index cafd6340f..d265ed4d3 100644 --- a/tiny-java-containers/helloworld/Dockerfile +++ b/tiny-java-containers/helloworld/Dockerfile @@ -12,7 +12,7 @@ RUN microdnf -y install wget xz && \ mv upx-${UPX_VERSION}-amd64_linux/upx . && \ rm -rf upx-${UPX_VERSION}-amd64_linux - # Compile the Hello class to Java bytecode +# Compile the Hello class to Java bytecode COPY Hello.java Hello.java RUN javac Hello.java # Build a native executable with native-image From 2b69cb887c2ff8d672f306a1cdba73c385379082 Mon Sep 17 00:00:00 2001 From: Shaun Smith Date: Mon, 28 Oct 2024 13:47:05 -0400 Subject: [PATCH 8/8] Removed sbom, binutils, updated README --- tiny-java-containers/README.md | 23 ++++++++++--------- .../Dockerfile.distroless-base.mostly | 2 +- .../Dockerfile.distroless-java-base.dynamic | 2 +- .../Dockerfile.distroless-java-base.jlink | 1 - .../Dockerfile.distroless-static.static | 2 +- .../jwebserver/Dockerfile.scratch.static | 2 +- .../jwebserver/Dockerfile.scratch.static-upx | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tiny-java-containers/README.md b/tiny-java-containers/README.md index 8339f2eb0..f92a5f54c 100644 --- a/tiny-java-containers/README.md +++ b/tiny-java-containers/README.md @@ -21,7 +21,8 @@ App](images/youtube.png)](https://youtu.be/6wYrAtngIVo) ## Prerequisites * x86 Linux (but the few binary dependencies could easily be changed for aarch64) -* Docker installed and running. It should work fine with [podman](https://podman.io/) but it has not been tested. +* Docker installed and running. It should work fine with + [podman](https://podman.io/) but it has not been tested. > NOTE: These instructions have only been tested on Linux x64. @@ -56,8 +57,8 @@ In a terminal, run: 1. The `hello` executable generated by GraalVM Native Image in the Dockerfile using the `--static --libc=musl` options is a fully self-contained executable. This means that it does not rely on any libraries in the host - operating system environment. This makes it easier to package in a variety of container images. - of Docker container images. + operating system environment. This makes it easier to package in a variety of + container images. 2. You can see in the output of the Dockerfile build that `ls -lh` reports the `hello` executable is ~4.9MB. There's no JVM, no JARs, no JIT compiler and @@ -72,8 +73,8 @@ In a terminal, run: ### Container Images -The size of the `scratch`-based container image is about the same size as the `hello.upx` -executable since it adds little overhead. +The size of the `scratch`-based container image is about the same size as the +`hello.upx` executable since it adds little overhead. ![](images/keyboard.jpg) `docker images hello` @@ -104,7 +105,7 @@ introduced in JDK 18 and build a containerized executable that serves up web pages. How small can a containerized Java web server be? Would you believe a measly -4.4MB? Let's see. +3.9 MB? Let's see. Let's move from the `helloworld` folder over to the `jwebserver` folder. @@ -139,7 +140,7 @@ jwebserver distroless-java de7f7efb6df4 4 minutes jwebserver temurin 643203bf8168 4 minutes ago 451MB jwebserver debian fa5bfa4b2e5e 4 minutes ago 932MB jwebserver distroless-java-base.jlink c3113c2400ea 5 minutes ago 122MB -jwebserver scratch.static-upx 75b3bb3249f3 5 minutes ago 4.12MB +jwebserver scratch.static-upx 75b3bb3249f3 5 minutes ago 3.9MB jwebserver alpine.static 178081760470 6 minutes ago 21.6MB jwebserver distroless-static.static 84053f6323c1 6 minutes ago 15.8MB jwebserver scratch.static 98061f48037c 6 minutes ago 13.8MB @@ -149,7 +150,7 @@ jwebserver distroless-java-base.dynamic 1aceeabbb329 7 minutes Sorting by size, it's clear that the fully statically linked GraalVM Native Image generated executable that's compressed and packaged on `scratch` -(`scratch.static-upx`) is the smallest at just 4.71MB, less than 4% of the size +(`scratch.static-upx`) is the smallest at just 3.9 MB, less than 4% of the size of the `jlink` version (`distroless-java-base.jlink`) running on the JVM. | Base Image | App Version | Size (MB) | @@ -163,16 +164,16 @@ of the `jlink` version (`distroless-java-base.jlink`) running on the JVM. | Alpine | native *fully* static linked | 21.60 | | Distroless Static | native *fully* static linked | 15.80 | | Scratch | native *fully* static linked | 13.80 | -| Scratch | *compressed* native *fully* static | 4.12 | +| Scratch | *compressed* native *fully* static | 3.90 | Running a container image is once again straight forward, just remember to map the server port, e.g.: -![](images/keyboard.jpg) `docker run --rm -p8000:8000 jwebserver:scratch.static` +![](images/keyboard.jpg) `docker run --init --rm -p8000:8000 jwebserver:scratch.static` or -![](images/keyboard.jpg) `docker run --rm -p8000:8000 jwebserver:scratch.static-upx` +![](images/keyboard.jpg) `docker run --init --rm -p8000:8000 jwebserver:scratch.static-upx` Using `curl` or your favourite tool you can hit `http://localhost:8000` to fetch the index.html file. diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly b/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly index 0c6082592..cda4e7c13 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-base.mostly @@ -1,7 +1,7 @@ FROM container-registry.oracle.com/graalvm/native-image:23 AS nativebuild WORKDIR /build # Build a native executable optimizing for size with `-Os` -RUN native-image --static-nolibc -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.mostly +RUN native-image --static-nolibc -Os -m jdk.httpserver -o jwebserver.mostly RUN ls -lh jwebserver.mostly FROM gcr.io/distroless/base-debian12 diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic index 25107158d..a1bc87ce1 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.dynamic @@ -1,7 +1,7 @@ FROM container-registry.oracle.com/graalvm/native-image:23 AS nativebuild WORKDIR /build # Build a dynamically linked native executable optimizing for size with `-Os` -RUN native-image -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.dynamic +RUN native-image -Os -m jdk.httpserver -o jwebserver.dynamic RUN ls -lh jwebserver.dynamic FROM gcr.io/distroless/java-base-debian12 diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink index 20f71e06f..066c8db8e 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-java-base.jlink @@ -1,5 +1,4 @@ FROM container-registry.oracle.com/graalvm/jdk:23 AS build -RUN microdnf install -y binutils WORKDIR /build # Build a runtime image optimized for size RUN jlink \ diff --git a/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static b/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static index 47e5630ef..b71362386 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static +++ b/tiny-java-containers/jwebserver/Dockerfile.distroless-static.static @@ -1,7 +1,7 @@ FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild WORKDIR /build # Build a statically linked native executable optimizing for size with `-Os` -RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN native-image --static --libc=musl -Os -m jdk.httpserver -o jwebserver.static RUN ls -lh jwebserver.static FROM gcr.io/distroless/static-debian12 diff --git a/tiny-java-containers/jwebserver/Dockerfile.scratch.static b/tiny-java-containers/jwebserver/Dockerfile.scratch.static index 02545ab17..595add728 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.scratch.static +++ b/tiny-java-containers/jwebserver/Dockerfile.scratch.static @@ -1,7 +1,7 @@ FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild WORKDIR /build # Build a statically linked native executable optimizing for size with `-Os` -RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN native-image --static --libc=musl -Os -m jdk.httpserver -o jwebserver.static RUN ls -lh jwebserver.static FROM scratch diff --git a/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx b/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx index 31fe91cd7..9aa0d6978 100644 --- a/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx +++ b/tiny-java-containers/jwebserver/Dockerfile.scratch.static-upx @@ -2,7 +2,7 @@ FROM container-registry.oracle.com/graalvm/native-image:23-muslib AS nativebuild WORKDIR /build # Build a statically linked native executable optimizing for size with `-Os` -RUN native-image --static --libc=musl -Os --enable-sbom=cyclonedx -m jdk.httpserver -o jwebserver.static +RUN native-image --static --libc=musl -Os -m jdk.httpserver -o jwebserver.static RUN ls -lh jwebserver.static # Install and use UPX