I try to deploy a function on AWS Lambda by a container image, but I cannot find an example of how to build it with the AWS lambda base image. Does Spring Cloud Function support this deploy method or only support deploying by a jar?
3 Answers
Yes, Spring Cloud Functions will work deployed as a container image. The process will be the same whether you use Spring Cloud Functions or another framework.
Here is an example Dockerfile from lambda-libs GitHub project.
# we'll use Amazon Linux 2 + Corretto 11 as our base
FROM public.ecr.aws/amazoncorretto/amazoncorretto:11 as base
# configure the build environment
FROM base as build
RUN yum install -y maven
WORKDIR /src
# cache and copy dependencies
ADD pom.xml .
RUN mvn dependency:go-offline dependency:copy-dependencies
# compile the function
ADD . .
RUN mvn package
# copy the function artifact and dependencies onto a clean base
FROM base
WORKDIR /function
COPY --from=build /src/target/dependency/*.jar ./
COPY --from=build /src/target/*.jar ./
# configure the runtime startup as main
ENTRYPOINT [ "/usr/bin/java", "-cp", "./*", "com.amazonaws.services.lambda.runtime.api.client.AWSLambda" ]
# pass the name of the function handler as an argument to the runtime
# in this case it'll be the special Spring Cloud Function handler
CMD [ "example.App::sayHello" ]

- 727
- 4
- 16
I think what you are asking is closely related to AWS Custom Runtime and indeed we do have support and sample for it - https://github.com/spring-cloud/spring-cloud-function/tree/main/spring-cloud-function-samples/function-sample-aws-custom

- 5,820
- 16
- 17
-
I am trying to run this sample on my AWS and I'm getting the following error "Exception in thread "main" java.lang.UnsupportedClassVersionError: com/example/LambdaApplication has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0". I've selected "AWS Custom Runtime" for my lambda and I have uploaded the zip from target. – vbgd Jul 28 '22 at 19:32
-
It just means that you have compiled your code with the version of Java that is not the version of the java runtime. What version of spring-cloud-function you are using. Also, if I remember correctly AWS supports java 11? – Oleg Zhurakousky Jul 29 '22 at 05:19
-
I've just tried to run the sample that you posted in your initial post. So the version of sprint-cloud-function is 4.0.0-SNAPSHOT. If I try to compile it with java 11 I get: "Module function-sample-aws-custom SDK 11 is not compatible with the source version 17. Upgrade Module SDK in project settings to 17 or higher." If I switch to java 17, I won't be able to run on AWS Lambda without adding a custom java 17 runtime. – vbgd Jul 29 '22 at 06:33
-
Just take the lates released version that is 3.2.6. It will work with Java 8 and 11 – Oleg Zhurakousky Aug 01 '22 at 13:07
For both approaches I ran this on Windows WSL2 Ubuntu 20.04 distro. Bash is at the root of the project directory. Here are my two Docker approaches (I was trying to figure this out step by step).
My docker build command
docker build . -t <image name>
You can test your image locally
#note external port = 9000, I left the default spring boot port of 8080
docker run -p 9000:8080 -t <build image name>
Approach A
You can compile your JAR outside of Docker in Maven or Gradle. I then have a docker build file to copy it into the Amazon published Java image. In my case I wanted to deploy my Spring Cloud function using Java 17.
Amazon publishes their ECR base images with higher Java versions (or lower if you need)
https://gallery.ecr.aws/lambda/java (find all Amazon Java images here)
In my Docker build file I did the following - note the handler name is what is for the latest version of Spring Cloud Function.
FROM public.ecr.aws/lambda/java:17
#the docker build command is running at my project root directory
COPY build/libs/<your jar name>.jar ${LAMBDA_TASK_ROOT}/lib/
CMD ["org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest"]
You should be able to run this image locally on your machine and test that this works.
Note: The JAR must be packaged be using the instructions on the Spring Cloud Function page for AWS lambda (https://docs.spring.io/spring-cloud-function/docs/current/reference/html/aws.html). See section Notes on JAR layout.
Approach B
I did write a file later to compile the entire JAR in docker and stick it in an Amazon AWS Java image in a multi-step build. Since Spring Boot comes with a Maven / Gradle wrapper I just used the wrapper instead of trying to install Maven / Gradle in the image itself.
# Use an official OpenJDK runtime as a parent image
FROM openjdk:17-jdk-slim
# Set the working directory to /app
WORKDIR /app
# Copy the application files <this is copies your entire java project dir>
COPY . /app
# Run the Gradle build
RUN ./gradlew clean build
#Copy the resulting JAR file to the ECR image
FROM public.ecr.aws/lambda/java:17
COPY --from=0 /app/build/libs/<INSERT project jar name>.jar ${LAMBDA_TASK_ROOT}/lib/
# Set the handler for AWS Lambda
CMD ["org.springframework.cloud.function.adapter.aws.FunctionInvoker::handleRequest"]

- 669
- 1
- 5
- 21