GraalVM’s documentation website served with jwebserver
in a Docker container on Oracle Cloud Infrastructure.
This example demonstrates how to optimize a Java application for file size taking advantage of different Native Image containerisation and linking options.
The various Dockerfiles copy a native executable or jlink
generated custom runtime image folder along with static website pages into a container image, and set the entrypoint.
The
jwebserver
tool is a minimal HTTP server for serving static files from a single directory hierarchy, added in Java 18.
- x86 Linux
- Docker (or Podman)
- GraalVM for JDK 23 Early Access build
- The
musl
toolchain
-
Clone this repository with Git:
git clone https://github.com/olyagpl/jwebserver-website-runner.git
-
To complete all steps in this demo, you need the following
zlib
packages installed: zlib.x86_64, zlib-devel.x86_64;zlib-static.x86_64. Enter the example directory and run the following script to download and configure themusl
toolchain, and installzlib
into the toolchain:cd jwebserver-website-runner
./setup-musl.sh
-
Download UPX, an advanced executable file compressor:
./setup-upx.sh
-
Using
jlink
, create a custom runtime for the application, package it into a container image that contains a JDK../build-jlink-runner.sh
-
Build a fully dynamically linked executable and package it in a distroless container image with just enough to run the application.
./build-dynamic-runner.sh
-
Build a mostly statically linked executable, by passing
--static-nolibc
to thenative-image
tool, and package it into a container image that providesglibc
../build-mostly-static-runner.sh
What can you do next to reduce the size even more?
-
Build a fully static executable, by passing
--static --libc=musl
to thenative-image
tool, and package it into a scratch container. (It requires themusl
toolchain.)./build-static-runner.sh
-
Compress the fully static executable, created at the previous step, with UPX, package it into a scratch container.
./build-static-compressed-runner.sh
Note that UPX loads the native executable into the memory, unpackages it, and then compresses.
Run any of the container images to serve the website, mapping the ports, for example:
docker run --rm -p8000:8000 website-runner:scratch.static
Finally, open the website in a browser at http://<SERVER_IP>:8080/, where the <SERVER_IP>
is the public API address of the remote host.
If you are running the example locally, not on a remote host, just open http://localhost:8000.
To stop a running container, find out the container image ID and stop it:
docker ps
docker stop <image id>
To clean up all images, run the ./clean.sh
script provided for that purpose.
Compare the sizes of the various Docker container images and native executables:
ls -lh runner*
docker images website-runner
Note that the website static pages added 44M to the container images size!