Skip to content

Commit

Permalink
Add workshop: Multi-Cloud Apps with GraalVM - Up and Running
Browse files Browse the repository at this point in the history
parent b1031bf
author Olya Gupalo <[email protected]> 1724918445 +0300
committer Olya Gupalo <[email protected]> 1725086369 +0300

parent b1031bf
author Olya Gupalo <[email protected]> 1724918445 +0300
committer Olya Gupalo <[email protected]> 1725086348 +0300

parent b1031bf
author Olya Gupalo <[email protected]> 1724918445 +0300
committer Olya Gupalo <[email protected]> 1725086251 +0300

parent b1031bf
author Olya Gupalo <[email protected]> 1724918445 +0300
committer Olya Gupalo <[email protected]> 1725086130 +0300

Add workshop: Multi-Cloud Apps with GraalVM - Up and Running
  • Loading branch information
olyagpl committed Sep 3, 2024
1 parent b1031bf commit f2326b2
Show file tree
Hide file tree
Showing 537 changed files with 119,487 additions and 5 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Github Actions Pipeline
on: [push, pull_request]
jobs:
build:
name: Run Jwebserver
runs-on: ubuntu-20.04 # Docker changed its behavior on Ubuntu 22.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
with:
java-version: '23-ea'
distribution: 'graalvm'
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run Spring Boot Web Server
run: |
# Build JAR (Debian Slim)
./build-jar.sh
#
# Build Jlink custom runtime (Distroless Java Base)
./build-jlink.sh
#
# Build dynamic image (Distroless Java Base)
./build-dynamic-image.sh
#
# Build dynamic image, optimized for size (Distroless Java Base)
./build-dynamic-image-optimized.sh
#
# Setup musl toolchain
./setup-musl.sh
export PATH="$PWD/musl-toolchain/bin:$PATH"
#
# Build mostly static image (Distroless Base)
./build-mostly-static-image.sh
#
# Build fully static image (Scratch)
./build-static-image.sh
#
# Download upx
./setup-upx.sh
#
# Build fully static compressed image (Scratch UPX)
./build-static-upx-image.sh
#
# Compare file sizes
ls -lh target/webserver*
docker images webserver
- name: Archive production artifacts
uses: actions/upload-artifact@v4
with:
name: native-binaries-${{ matrix.os }}
path: |
target/webserver*
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependencies
upx
x86_64-linux-musl-native/
zlib-1.2.13/

# Build results
jlink-jre/
webserver.dynamic
webserver.mostly-static
webserver.static
webserver.static-upx
webserver-sbom
webserver-compacted-gc
cp.txt
target/

# VS Code
.vscode/
.DS_Store

Binary file added .mvn/wrapper/maven-wrapper.jar
Binary file not shown.
18 changes: 18 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
9 changes: 9 additions & 0 deletions Dockerfile.debian-slim.uber-jar
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM container-registry.oracle.com/graalvm/jdk:21 AS build
COPY . /webserver
WORKDIR /webserver
RUN ./mvnw clean package

FROM gcr.io/distroless/java21-debian12
COPY --from=build /webserver/target/webserver-0.0.1-SNAPSHOT.jar webserver-0.0.1-SNAPSHOT.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "webserver-0.0.1-SNAPSHOT.jar"]
4 changes: 4 additions & 0 deletions Dockerfile.distroless-base.mostly
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM gcr.io/distroless/base-debian12
COPY target/webserver.mostly-static /
EXPOSE 8080
ENTRYPOINT ["/webserver.mostly-static"]
4 changes: 4 additions & 0 deletions Dockerfile.distroless-java-base.dynamic
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM gcr.io/distroless/java-base-debian12
COPY target/webserver /
EXPOSE 8080
ENTRYPOINT ["/webserver"]
4 changes: 4 additions & 0 deletions Dockerfile.distroless-java-base.dynamic-optimized
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM gcr.io/distroless/java-base-debian12
COPY target/webserver.dynamic-optimized /
EXPOSE 8080
ENTRYPOINT ["/webserver.dynamic-optimized"]
22 changes: 22 additions & 0 deletions Dockerfile.distroless-java-base.jlink
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM container-registry.oracle.com/graalvm/jdk:21 AS build
COPY . /webserver
WORKDIR /webserver
RUN ./mvnw clean package
RUN ./mvnw dependency:build-classpath -Dmdep.outputFile=cp.txt
RUN jdeps --ignore-missing-deps -q --recursive --multi-release 21 --print-module-deps --class-path $(cat cp.txt) target/webserver-0.0.1-SNAPSHOT.jar
RUN jlink \
--module-path ${JAVA_HOME}/jmods \
--add-modules java.base,java.compiler,java.desktop,java.instrument,java.management,java.naming,java.net.http,java.prefs,java.rmi,java.scripting,java.security.jgss,java.sql,jdk.jfr,jdk.unsupported,org.graalvm.nativeimage \
--verbose \
--strip-debug \
--compress zip-9 \
--no-header-files \
--no-man-pages \
--strip-java-debug-attributes \
--output jlink-jre

FROM gcr.io/distroless/java-base-debian12
COPY --from=build /webserver/target/webserver-0.0.1-SNAPSHOT.jar webserver-0.0.1-SNAPSHOT.jar
COPY --from=build /webserver/jlink-jre jlink-jre
EXPOSE 8080
ENTRYPOINT ["jlink-jre/bin/java", "-jar", "webserver-0.0.1-SNAPSHOT.jar"]
5 changes: 5 additions & 0 deletions Dockerfile.scratch.static
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch
WORKDIR /tmp
COPY target/webserver.static /
EXPOSE 8080
ENTRYPOINT ["/webserver.static"]
5 changes: 5 additions & 0 deletions Dockerfile.scratch.static-upx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM scratch
WORKDIR /tmp
COPY target/webserver.static-upx /
EXPOSE 8080
ENTRYPOINT ["/webserver.static-upx"]
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
# Multi-Cloud Apps with GraalVM - Up and Running

This workshop is for developers looking to understand better how to **build size-optimized cloud native Java applications** using [GraalVM Native Image](https://docs.oracle.com/en/graalvm/jdk/22/docs/reference-manual/native-image/). You are going to discover ways to minimize application footprint by taking advantage of different Native Image linking options and packaging into various base containers.
This workshop is for developers looking to understand better how to **build size-optimized cloud native Java applications** using [GraalVM Native Image](https://www.graalvm.org/jdk21/reference-manual/native-image/). You are going to discover ways to minimize application footprint by taking advantage of different Native Image linking options and packaging into various base containers.

For the demo part, you will run a Spring Boot web server application, hosting the GraalVM website.
Spring Boot 3 has integrated support for GraalVM Native Image, making it easier to set up and configure a project.
This application is enhanced with the [GraalVM Native Image Maven plugin](https://graalvm.github.io/native-build-tools/latest/index.html).
Compiling a Spring Boot application ahead of time can significantly boost the performance and reduce its footprint.

### Workshop Objectives
Expand Down Expand Up @@ -97,7 +96,7 @@ See how much reduction in size you can gain.

Jlink, or `jlink`, is a tool that generates a custom Java runtime image that contains only the platform modules that are required for your application. This is one of the approaches to create cloud native applications introduced in Java 11.

The script _build-jlink-runner.sh_ that runs `docker build` using the _Dockerfile.distroless-java-base.jlink_.
The script _build-jlink.sh_ that runs `docker build` using the _Dockerfile.distroless-java-base.jlink_.
The Dockerfile contains a multistage build: first it generates a Jlink custom runtime on a full JDK; then copies the runtime image folder along with static website pages into a Java base container image, and sets the entrypoint.

The application does not have to be modular, but you need to figure out which modules the application depends on to be able to `jlink` it.
Expand Down Expand Up @@ -304,6 +303,9 @@ The script _build-dynamic-image.sh_, available in this repository for your conve
### Action
1. This step requires to install [GraalVM for JDK 23 Early Access Build](https://github.com/graalvm/oracle-graalvm-ea-builds/releases). Run the commands one by one:
```
cd ..
```
```bash
wget -q https://github.com/graalvm/oracle-graalvm-ea-builds/releases/download/jdk-23.0.0-ea.23/graalvm-jdk-23.0.0-ea.23_linux-x64_bin.tar.gz && tar -xzf graalvm-jdk-23.0.0-ea.23_linux-x64_bin.tar.gz && rm -f graalvm-jdk-23.0.0-ea.23_linux-x64_bin.tar.gz
```
Expand All @@ -319,6 +321,9 @@ The script _build-dynamic-image.sh_, available in this repository for your conve
```bash
java -version
```
```
cd spring-boot-webserver
```
2. Run the script to build a size-optimized native executable and package it into a container:
```bash
Expand Down Expand Up @@ -517,7 +522,7 @@ A separate Maven profile exists for this step:
```
The container size shrinked to **96.4MB**! A _scratch_ container weights only **14.5MB**.

## **STEP 9**: Compress a Static Native Image with UPX and Run Inside a Container
## **STEP 8**: Compress a Static Native Image with UPX and Run Inside a Container

_Not convincing? What can you do next to reduce the size even more?_

Expand Down Expand Up @@ -584,7 +589,7 @@ It can significantly reduce the executable size, but note, that UPX loads the ex
The container size reduced dramatically to just **36.2MB**.
The application and container image's size were now shrinked to the minimum.
## **STEP 10**: Clean up (Optional)
## **STEP 9**: Clean up (Optional)
To clean up all images, run the `./clean.sh` script provided for that purpose.
Expand Down
14 changes: 14 additions & 0 deletions build-all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

./build-jar.sh
./build-jlink.sh
./build-dynamic-image.sh
./build-mostly-static-image.sh
./build-static-image.sh
./build-static-upx-image.sh

echo "Generated Executables"
ls -lh target/webserver*

echo "Generated Docker Container Images"
docker images webserver
7 changes: 7 additions & 0 deletions build-dynamic-image-optimized.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Compile with fully dynamically linked shared libraries; optimize for size
./mvnw -Dmaven.test.skip=true -Pdynamic-size-optimized native:compile

# Distroless Java Base-provides glibc and other libraries needed by the JDK
docker build . -f Dockerfile.distroless-java-base.dynamic-optimized -t webserver:distroless-java-base.dynamic-optimized
7 changes: 7 additions & 0 deletions build-dynamic-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Compile with fully dynamically linked shared libraries
./mvnw -Dmaven.test.skip=true native:compile

# Distroless Java Base-provides glibc and other libraries needed by the JDK
docker build . -f Dockerfile.distroless-java-base.dynamic -t webserver:distroless-java-base.dynamic
4 changes: 4 additions & 0 deletions build-jar.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

# Distroless Java Base-provides glibc and other libraries needed by the JDK
docker build . -f Dockerfile.debian-slim.uber-jar -t webserver:debian-slim.jar
6 changes: 6 additions & 0 deletions build-jlink.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

rm -rf jlink-jre cp.txt

# Distroless Java Base-provides glibc and other libraries needed by the JDK
docker build . -f Dockerfile.distroless-java-base.jlink -t webserver:distroless-java-base.jlink
7 changes: 7 additions & 0 deletions build-mostly-static-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Compile linking zlib and JDK shared libraries except the standard C library (libc); optimize for size
./mvnw -Dmaven.test.skip=true -Pnative,mostly-static native:compile

# Distroless Base (provides glibc)
docker build . -f Dockerfile.distroless-base.mostly -t webserver:distroless-base.mostly-static
12 changes: 12 additions & 0 deletions build-static-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

TOOLCHAIN_DIR=${SCRIPT_DIR}/musl-toolchain
PATH=${TOOLCHAIN_DIR}/bin:${PATH}

# Create a statically linked binary that can be used without any additional library dependencies; optimize for size
./mvnw -Dmaven.test.skip=true -Pnative,fully-static native:compile

# Scratch-nothing
docker build . -f Dockerfile.scratch.static -t webserver:scratch.static
9 changes: 9 additions & 0 deletions build-static-upx-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/sh

rm -f target/webserver.static-upx

# Compress with UPX
./upx --lzma --best -o target/webserver.static-upx target/webserver.static

# Scratch--fully static and compressed
docker build . -f Dockerfile.scratch.static-upx -t webserver:scratch.static-upx
6 changes: 6 additions & 0 deletions clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
set +e

./mvnw clean
rm -rf jlink-jre cp.txt
docker images webserver -q | grep -v TAG | awk '{print($1)}' | xargs docker rmi
Loading

0 comments on commit f2326b2

Please sign in to comment.