Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ steps:
command: |
docker build -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME} .
docker tag ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:latest ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:$buildId

outputArtifacts:
- name: image-jvm
type: DOCKER_IMAGE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,45 @@ component: build
timeoutInSeconds: 5000
shell: bash
env:
variables:
"JAVA_HOME" : "/usr/lib64/graalvm/graalvm-java23"
exportedVariables:
- buildId
# https://docs.oracle.com/en/graalvm/jdk/23/docs/getting-started/oci/devops-build-pipeline/#prerequisites
steps:
- type: Command
command: |
buildId=`echo ${OCI_BUILD_RUN_ID} | rev | cut -c 1-6 | rev`
echo "Build ID: $buildId"
- type: Command
command: |
yum -y install graalvm-23-native-image
- type: Command
command: |
export PATH=$JAVA_HOME/bin:$PATH
- type: Command
command: |
mvn package
- type: Command
command: |
native-image \
-H:ReflectionConfigurationFiles=reflection.json \
-Ob \
-H:Name=Hello \
-cp "target/Hellofunc-1.0-SNAPSHOT-jar-with-dependencies.jar" \
com.fnproject.fn.runtime.EntryPoint
- type: Command
command: |
docker build -f Dockerfile.native -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME} .
docker tag ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:latest ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:$buildId
# Alternate (faster) method of pushing if don't want to wait outputArtifacts getting executed (stage can be removed from build pipeline)
# This does not require personal Docker credentials (!)
- type: Command
command: |
yum install jq -y
oci raw-request --region eu-frankfurt-1 --http-method GET --target-uri 'https://fra.ocir.io/20180419/docker/token' --auth=resource_principal | jq -r .data.token | docker login -u BEARER_TOKEN --password-stdin fra.ocir.io
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:$buildId

outputArtifacts:
- name: image-native
type: DOCKER_IMAGE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,39 +116,18 @@ GraalVM compiles your Java functions ahead of time into standalone binaries that

<p>

To do this a Docker multi-stage build is used.

To do this a <a href="https://github.com/oracle-devrel/technology-engineering/tree/main/app-dev/devops-and-containers/devops/oci-devops-terraform-function-java-graalvm">create OCI DevOps project for a Function CI/CD</a> and then clone the repo and copy the following files with the Function source and commit and push them to the repo:
<p>

Before building the native image let's do a full maven build for the project to create the necessary libraries under <code>target/lib</code>:

<pre>
mvn clean install
</pre>

Then build the Docker container using <a href="./files/Dockerfile.native">multi-stage Docker file</a> including the GraalVM native image compilation:

<pre>
docker build -f Dockerfile.native -t fra.ocir.io/&lt;YOUR OCI TENANCY NAMESPACE&gt;/helloworldai-java:2 .
</pre>

The GraalVM compilation stage requires quite a bit resources from your localhost so in case for example using Rancher desktop
think of increasing the CPU and memory for it to make the build faster.

<ul>
<li>Dockerfile.native</li>
<li>build_spec_native.yaml</li>
<li>reflection.json</li>
<li>pom.xml</li>
</ul>
<p>

In the <a href="./files/Dockerfile.native">Dockerfile.native</a> two things are important: Including the <a href="./files/reflection.json">reflection.json</a> with the proper function class name and passing Fn FDK libraries with <code>"-Djava.library.path=/lib"</code> in the container CMD along with the <code>"com.example.HelloAIFunction::handleRequest"</code> function handler.

After pushing run the native build pipeline and test the Function in cloud shell.
<p>

After the build push the container to OCIR repo:

<pre>
docker push fra.ocir.io/&lt;YOUR OCI TENANCY NAMESPACE&gt;/helloworldai-java:2
</pre>

Finally deploy the container to your OCI Function by replacing the container using the Cloud UI by editing the function and changing the container from <code>helloworldai-java:1</code> to <code>helloworldai-java:2</code>. Then test it.


# Useful Links

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,4 @@
FROM fnproject/fn-java-fdk-build:jdk17-1.0-latest as build-stage
WORKDIR /function
ENV MAVEN_OPTS -Dhttp.proxyHost= -Dhttp.proxyPort= -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.nonProxyHosts= -Dmaven.repo.local=/usr/share/maven/ref/repository
ADD pom.xml /function/pom.xml
RUN ["mvn", "package", "dependency:copy-dependencies", "-DincludeScope=runtime", "-DskipTests=true", "-Dmdep.prependGroupId=true", "-DoutputDirectory=target", "--fail-never"]
ADD src /function/src
RUN ["mvn", "package"]

FROM container-registry.oracle.com/graalvm/native-image:23-ol8 AS native
WORKDIR /app
COPY --from=build-stage /function/target .
ADD reflection.json .

RUN native-image \
-H:ReflectionConfigurationFiles=/app/reflection.json \
-Ob \
-H:Name=Hello \
-cp "/app/Hellofunc-1.0-SNAPSHOT.jar:/app/*" \
com.fnproject.fn.runtime.EntryPoint

FROM fnproject/fn-java-fdk:jre17-latest as fdk

FROM container-registry.oracle.com/os/oraclelinux:8-slim
COPY --from=native /app/Hello .
COPY --from=fdk /function/runtime/* ./
FROM fnproject/fn-java-fdk:jre17-latest
COPY Hello ./
ENTRYPOINT [ "./Hello" ]
CMD [ "com.example.fn.HelloFunction::handleRequest", "-Djava.library.path=/lib"]
CMD [ "com.example.fn.HelloFunction::handleRequest", "-Djava.library.path=/function/runtime/lib"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,45 @@ component: build
timeoutInSeconds: 5000
shell: bash
env:
variables:
"JAVA_HOME" : "/usr/lib64/graalvm/graalvm-java23"
exportedVariables:
- buildId
# https://docs.oracle.com/en/graalvm/jdk/23/docs/getting-started/oci/devops-build-pipeline/#prerequisites
steps:
- type: Command
command: |
buildId=`echo ${OCI_BUILD_RUN_ID} | rev | cut -c 1-6 | rev`
echo "Build ID: $buildId"
- type: Command
command: |
yum -y install graalvm-23-native-image
- type: Command
command: |
export PATH=$JAVA_HOME/bin:$PATH
- type: Command
command: |
mvn package
- type: Command
command: |
native-image \
-H:ReflectionConfigurationFiles=reflection.json \
-Ob \
-H:Name=Hello \
-cp "target/Hellofunc-1.0-SNAPSHOT-jar-with-dependencies.jar" \
com.fnproject.fn.runtime.EntryPoint
- type: Command
command: |
docker build -f Dockerfile.native -t ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME} .
docker tag ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:latest ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:$buildId
# Alternate (faster) method of pushing if don't want to wait outputArtifacts getting executed (stage can be removed from build pipeline)
# This does not require personal Docker credentials (!)
- type: Command
command: |
yum install jq -y
oci raw-request --region eu-frankfurt-1 --http-method GET --target-uri 'https://fra.ocir.io/20180419/docker/token' --auth=resource_principal | jq -r .data.token | docker login -u BEARER_TOKEN --password-stdin fra.ocir.io
docker push ${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}:$buildId

outputArtifacts:
- name: image-native
type: DOCKER_IMAGE
Expand Down