Deploy Java Lambda functions with container images - AWS Lambda

Deploy Java Lambda functions with container images

You can deploy your Lambda function code as a container image. To help you build a container image for your Java function, AWS provides the following resources:

  • AWS base images for Lambda

    These base images are preloaded with a language runtime and other components that are required to run the image on Lambda. AWS provides a Dockerfile for each of the base images to help with building your container image.

  • Open-source runtime interface clients

    If you use a community or private enterprise base image, you must add a runtime interface client to the base image to make it compatible with Lambda.

  • Open-source runtime interface emulator

    Lambda provides a runtime interface emulator (RIE) for you to test your function locally. The base images for Lambda and base images for custom .runtimes include the RIE. For other base images, you can download the RIE for testing your image locally.

The workflow for a function defined as a container image includes these steps:

  1. Build your container image using the resources listed in this topic.

  2. Upload the image to your Amazon Elastic Container Registry (Amazon ECR) container registry.

  3. Create the function or update the function code to deploy the image to an existing function.

AWS base images for Java

AWS provides the following base images for Java:

Tags Runtime Operating system Dockerfile Deprecation

17

Java 17 Amazon Linux 2 Dockerfile for Java 17 on GitHub

11

Java 11 Amazon Linux 2 Dockerfile for Java 11 on GitHub

8.al2

Java 8 Amazon Linux 2 Dockerfile for Java 8 on GitHub

8

Java 8 Amazon Linux Dockerfile for Java 8 on GitHub

Amazon ECR repository: gallery.ecr.aws/lambda/java

Using a Java base image

To complete the steps in this section, you must have the following:

Maven
  1. Run the following command to create a Maven project using the archetype for Lambda. The following parameters are required:

    • service – The AWS service client to use in the Lambda function. For a list of available sources, see aws-sdk-java-v2/services on GitHub.

    • region – The AWS Region where you want to create the Lambda function.

    • groupId – The full package namespace of your application.

    • artifactId – Your project name. This becomes the name of the directory for your project.

    mvn -B archetype:generate \ -DarchetypeGroupId=software.amazon.awssdk \ -DarchetypeArtifactId=archetype-lambda -Dservice=s3 -Dregion=US_WEST_2 \ -DgroupId=com.example.myapp \ -DartifactId=myapp

    The Maven archetype for Lambda is preconfigured to compile with Java SE 8 and includes a dependency to the AWS SDK for Java. If you create your project with a different archetype or by using another method, you must configure the Java compiler for Maven and declare the SDK as a dependency.

  2. Open the /myapp/src/main/java/com/example/myapp directory, and find the App.java file. This is the code for the Lambda function. You can use the provided sample code for testing, or replace it with your own.

  3. Create a new Dockerfile with the following configuration:

    • Set the FROM property to the URI of the base image.

    • Set the CMD argument to the Lambda function handler.

    Example Dockerfile
    FROM public.ecr.aws/lambda/java:11 # Copy function code and runtime dependencies from Maven layout COPY target/classes ${LAMBDA_TASK_ROOT} COPY target/dependency/* ${LAMBDA_TASK_ROOT}/lib/ # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "com.example.myapp.App::handleRequest" ]
  4. Compile the project and collect the runtime dependencies.

    mvn compile dependency:copy-dependencies -DincludeScope=runtime
  5. Build the Docker image with the docker build command. The following example names the image docker-image and gives it the test tag.

    docker build -t docker-image:test .
(Optional) Test the image locally
  1. Start the Docker image with the docker run command. In this example, docker-image is the image name and test is the tag.

    docker run -p 9000:8080 docker-image:test

    This command runs the image as a container and creates a local endpoint at localhost:9000/2015-03-31/functions/function/invocations.

  2. Test your application locally using the RIE. From a new terminal window, post an event to the following endpoint using a curl command:

    curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

    This command invokes the function running in the container image and returns a response.

  3. Get the container ID.

    docker ps
  4. Use the docker kill command to stop the container. In this command, replace 3766c4ab331c with the container ID from the previous step.

    docker kill 3766c4ab331c
Gradle
  1. Create a directory for the project, and then switch to that directory.

    mkdir example cd example
  2. Run the following command to have Gradle generate a new Java application project in the example directory in your environment. To accept the default options provided in the interactive experience, press Enter.

    gradle init --type java-application
  3. Open the /example/app/src/main/java/example directory, and find the App.java file. This is the code for the Lambda function. You can use the following sample code for testing, or replace it with your own.

    Example App.java
    package com.example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; public class App implements RequestHandler<Object, String> { public String handleRequest(Object input, Context context) { return "Hello world!"; } }
  4. Open the build.gradle file. If you're using the sample function code from the previous step, replace the contents of build.gradle with the following. If you're using your own function code, modify your build.gradle file as needed.

    plugins { id 'java' } group 'com.example' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.1' } jar { manifest { attributes 'Main-Class': 'com.example.App' } }
  5. The gradle init command from step 2 also generated a dummy test case in the app/test directory. For the purposes of this tutorial, skip running tests by deleting the /test directory.

  6. Build the project.

    gradle build
  7. In the project's root directory (/example), create a Dockerfile with the following configuration:

    • Set the FROM property to the URI of the base image.

    • Use the COPY command to copy the function code and runtime dependencies to {LAMBDA_TASK_ROOT}.

    • Set the CMD argument to the Lambda function handler.

    Example Dockerfile
    FROM public.ecr.aws/lambda/java:11 # Copy function code and runtime dependencies from Gradle layout COPY app/build/classes/java/main ${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "com.example.App::handleRequest" ]
  8. Build the Docker image with the docker build command. The following example names the image docker-image and gives it the test tag.

    docker build -t docker-image:test .
(Optional) Test the image locally
  1. Start the Docker image with the docker run command. In this example, docker-image is the image name and test is the tag.

    docker run -p 9000:8080 docker-image:test

    This command runs the image as a container and creates a local endpoint at localhost:9000/2015-03-31/functions/function/invocations.

  2. Test your application locally using the RIE. From a new terminal window, post an event to the following endpoint using a curl command:

    curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

    This command invokes the function running in the container image and returns a response.

  3. Get the container ID.

    docker ps
  4. Use the docker kill command to stop the container. In this command, replace 3766c4ab331c with the container ID from the previous step.

    docker kill 3766c4ab331c
To upload the image to Amazon ECR and create the Lambda function
  1. Run the get-login-password command to authenticate the Docker CLI to your Amazon ECR registry.

    • Set the --region value to the AWS Region where you want to create the Amazon ECR repository.

    • Replace 111122223333 with your AWS account ID.

    aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
  2. Create a repository in Amazon ECR using the create-repository command.

    aws ecr create-repository --repository-name hello-world --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE

    If successful, you see a response like this:

    { "repository": { "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world", "createdAt": "2023-03-09T10:39:01+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": true }, "encryptionConfiguration": { "encryptionType": "AES256" } } }
  3. Copy the repositoryUri from the output in the previous step.

  4. Run the docker tag command to tag your local image into your Amazon ECR repository as the latest version. In this command:

    • Replace docker-image:test with the name and tag of your Docker image.

    • Replace the Amazon ECR repository URI with the repositoryUri that you copied. Make sure to include :latest at the end of the URI.

    docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  5. Run the docker push command to deploy your local image to the Amazon ECR repository. Make sure to include :latest at the end of the repository URI.

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. Create an execution role for the function, if you don't already have one. You need the Amazon Resource Name (ARN) of the role in the next step.

  7. Create the Lambda function. For ImageUri, specify the repository URI from earlier. Make sure to include :latest at the end of the URI.

    aws lambda create-function \ --function-name hello-world \ --package-type Image \ --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \ --role arn:aws:iam::111122223333:role/lambda-ex
  8. Invoke the function.

    aws lambda invoke --function-name hello-world response.json

    You should see a response like this:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. To see the output of the function, check the response.json file.

To update the function code, you must create a new image version and store the image in the Amazon ECR repository. For more information, see Updating function code.

Java runtime interface clients

Install the runtime interface client for Java using the Apache Maven package manager. Add the following to your pom.xml file:

<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> <version>2.3.1</version> </dependency>

For package details, see AWS Lambda Java Runtime Interface Client in Maven Central Repository.

You can also view the Java client source code in the AWS Lambda Java Support Libraries repository on GitHub.