

# Implantar funções do Lambda em Java com imagens de contêiner
<a name="java-image"></a>

Existem três maneiras de criar uma imagem de contêiner para uma função do Lambda em Java:
+ [Usar uma imagem base da AWS para Java](#java-image-instructions)

  As [imagens base da AWS](images-create.md#runtimes-images-lp) são pré-carregadas com um  runtime de linguagem, um cliente de interface de runtime para gerenciar a interação entre o Lambda e o código da sua função e um emulador de interface de runtime para testes locais.
+ [Usar uma imagem base somente para sistema operacional da AWS](images-create.md#runtimes-images-provided)

  [As imagens base somente para sistema operacional da AWS](https://gallery.ecr.aws/lambda/provided) contêm uma distribuição do Amazon Linux e o [emulador de interface de runtime](https://github.com/aws/aws-lambda-runtime-interface-emulator/). Essas imagens são comumente usadas para criar imagens de contêiner para linguagens compiladas, como [Go](go-image.md#go-image-provided) e [Rust](lambda-rust.md) e para uma linguagem ou versão de linguagem para a qual o Lambda não fornece uma imagem base, como Node.js 19. Também é possível usar imagens base somente para sistema operacional para implementar um [runtime personalizado](runtimes-custom.md). Para tornar a imagem compatível com o Lambda, você deve incluir [o cliente de interface de runtime do Java](#java-image-clients) na imagem.
+ [Usar uma imagem base que não é da AWS](#java-image-clients)

  Também é possível usar uma imagem base alternativa de outro registro de contêiner, como Alpine Linux ou Debian. Também é possível usar uma imagem personalizada criada por sua organização. Para tornar a imagem compatível com o Lambda, você deve incluir [o cliente de interface de runtime do Java](#java-image-clients) na imagem.

**dica**  
Para reduzir o tempo necessário para que as funções do contêiner do Lambda se tornem ativas, consulte [Use multi-stage builds](https://docs.docker.com/build/building/multi-stage/) na documentação do Docker. Para criar imagens de contêiner eficientes, siga as [Melhores práticas para gravar Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/).

Esta página explica como criar, testar e implantar imagens de contêiner para o Lambda.

**Topics**
+ [Imagens base da AWS para Java](#java-image-base)
+ [Usar uma imagem base da AWS para Java](#java-image-instructions)
+ [Usar uma imagem base alternativa com o cliente da interface de runtime](#java-image-clients)

## Imagens base da AWS para Java
<a name="java-image-base"></a>

A AWS oferece as seguintes imagens base para Java:


| Tags | Runtime | Sistema operacional | Dockerfile | Desaprovação | 
| --- | --- | --- | --- | --- | 
| 25 | Java 25 | Amazon Linux 2023 | [Dockerfile para Java 25 no GitHub](https://github.com/aws/aws-lambda-base-images/blob/java25/Dockerfile.java25) |   30 de junho de 2029   | 
| 21 | Java 21 | Amazon Linux 2023 | [Dockerfile para Java 21 no GitHub](https://github.com/aws/aws-lambda-base-images/blob/java21/Dockerfile.java21) |   30 de junho de 2029   | 
| 17 | Java 17 | Amazon Linux 2 | [Dockerfile para Java 17 no GitHub](https://github.com/aws/aws-lambda-base-images/blob/java17/Dockerfile.java17) |   30º de junho de 2027   | 
| 11 | Java 11 | Amazon Linux 2 | [Dockerfile para Java 11 no GitHub](https://github.com/aws/aws-lambda-base-images/blob/java11/Dockerfile.java11) |   30º de junho de 2027   | 
| 8.al2 | Java 8 | Amazon Linux 2 | [Dockerfile para Java 8 no GitHub](https://github.com/aws/aws-lambda-base-images/blob/java8.al2/Dockerfile.java8.al2) |   30º de junho de 2027   | 

Repositório do Amazon ECR: [gallery.ecr.aws/lambda/java](https://gallery.ecr.aws/lambda/java)

As imagens base do Java 21 e posteriores são baseadas na [imagem de contêiner mínimo do Amazon Linux 2023](https://docs.aws.amazon.com/linux/al2023/ug/minimal-container.html). Imagens base anteriores usam o Amazon Linux 2. O AL2023 oferece várias vantagens em relação ao Amazon Linux 2, incluindo uma área de implantação menor e versões atualizadas de bibliotecas, como `glibc`.

As imagens baseadas no AL2023 usam o `microdnf` (com link simbólico `dnf`) como o gerenciador de pacotes, em vez do `yum`, que é o gerenciador de pacotes padrão no Amazon Linux 2. O `microdnf` é uma implementação autônoma do `dnf`. Para obter uma lista dos pacotes incluídos nas imagens baseadas no AL2023, consulte as colunas **Contêiner mínimo** em [Comparar pacotes instalados em imagens de contêiner do Amazon Linux 2023](https://docs.aws.amazon.com/linux/al2023/ug/al2023-container-image-types.html). Para obter mais informações sobre as diferenças entre o AL2023 e o Amazon Linux 2, consulte [Introdução ao runtime do Amazon Linux 2023 para AWS Lambda](https://aws.amazon.com/blogs/compute/introducing-the-amazon-linux-2023-runtime-for-aws-lambda/) no blog AWS Compute.

**nota**  
Para executar imagens baseadas no AL2023 localmente, inclusive com o AWS Serverless Application Model (AWS SAM), você deve usar o Docker versão 20.10.10 ou posterior.

## Usar uma imagem base da AWS para Java
<a name="java-image-instructions"></a>

### Pré-requisitos
<a name="java-image-prerequisites"></a>

Para executar as etapas desta seção, você deve ter o seguinte:
+ Java (por exemplo, [Amazon Corretto](https://aws.amazon.com/corretto))
+ [Apache Maven](https://maven.apache.org/) ou [Gradle](https://gradle.org/install/)
+ [AWS CLI versão 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (versão mínima 25.0.0)
+ O plug-in [buildx](https://github.com/docker/buildx/blob/master/README.md) do Docker.

### Criação de uma imagem a partir de uma imagem base
<a name="java-image-create"></a>

------
#### [ Maven ]

1. Execute o comando a seguir para criar um projeto de Maven usando o [arquétipo para Lambda](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda). Os seguintes parâmetros são obrigatórios:
   + **serviço**: o cliente AWS service (Serviço da AWS) a ser usado na função do Lambda. Para obter uma lista das origens disponíveis, consulte [aws-sdk-java-v2/services](https://github.com/aws/aws-sdk-java-v2/tree/master/services) no GitHub.
   + **região**: a Região da AWS na qual você deseja criar a função do Lambda.
   + **groupId**: o namespace completo do pacote da sua aplicação.
   + **artifactId**: o nome do seu projeto. Esse será o nome do diretório do projeto.

   No Linux e no macOS, execute este comando:

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

   No PowerShell, execute este comando:

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

   O arquétipo do Maven para Lambda é pré-configurado para compilar com o Java SE 8 e inclui uma dependência para o AWS SDK para Java. Se você criar seu projeto com um arquétipo diferente ou usando outro método, deverá [configurar o compilador Java para Maven](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#configure-maven-compiler) e [declarar o SDK como uma dependência](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#configure-maven-compiler).

1. Abra o diretório `myapp/src/main/java/com/example/myapp` e localize o arquivo `App.java`. Este é o código da função do Lambda. É possível usar o código de exemplo fornecido para testes ou substituí-lo pelo seu.

1. Navegue de volta para o diretório raiz do projeto e, em seguida, crie um Dockerfile com a seguinte configuração:
   + Defina a propriedade `FROM` como o [URI da imagem base](https://gallery.ecr.aws/lambda/java).
   + Defina o argumento `CMD` como o manipulador de funções do Lambda.

   Observe que o Dockerfile de exemplo não inclui uma [instrução USER](https://docs.docker.com/reference/dockerfile/#user). Quando você implanta uma imagem de contêiner no Lambda, o Lambda define automaticamente um usuário padrão do Linux com permissões de privilégio mínimo. Isso é diferente do comportamento padrão do Docker, que adota o usuário `root` como padrão quando nenhuma instrução `USER` é fornecida.  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/java:21
     
   # 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" ]
   ```

1. Compile o projeto e colete as dependências do runtime.

   ```
   mvn compile dependency:copy-dependencies -DincludeScope=runtime
   ```

1. Crie a imagem do Docker com o comando [docker build](https://docs.docker.com/engine/reference/commandline/build/). O exemplo a seguir nomeia a imagem como `docker-image` e atribui a ela a [tag](https://docs.docker.com/engine/reference/commandline/build/#tag) `test`. Para tornar sua imagem compatível com o Lambda, é necessário usar a opção `--provenance=false`.

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**nota**  
O comando especifica a opção `--platform linux/amd64` para garantir que seu contêiner seja compatível com o ambiente de execução do Lambda, independentemente da arquitetura da sua máquina de compilação. Se você pretende criar uma função do Lambda usando a arquitetura do conjunto de instruções ARM64, certifique-se de alterar o comando para usar a opção `--platform linux/arm64` em vez disso.

------
#### [ Gradle ]

1. Crie um diretório para o projeto e depois mude para esse diretório.

   ```
   mkdir example
   cd example
   ```

1. Execute o comando a seguir para que o Gradle gere um novo projeto de aplicação Java no diretório `example` em seu ambiente. Em **Selecionar DSL de script de compilação**, escolha **2: Groovy**.

   ```
   gradle init --type java-application
   ```

1. Abra o diretório `/example/app/src/main/java/example` e localize o arquivo `App.java`. Este é o código da função  do Lambda. É possível usar o código de exemplo a seguir para fins de teste ou substituí-lo pelo seu próprio código.  
**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!";
       }
   }
   ```

1. Abra o arquivo `build.gradle`. Se você estiver usando o exemplo de código de função da etapa anterior, substitua o conteúdo de `build.gradle` pelo conteúdo a seguir. Se você estiver usando seu próprio código de função, modifique seu arquivo `build.gradle` conforme necessário.  
**Example build.gradle (DSL Groovy)**  

   ```
   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'
     }
   }
   ```

1. O comando `gradle init` da etapa 2 também gerou um caso de teste fictício no diretório `app/test`. Para os fins deste tutorial, pule a execução de testes excluindo o diretório `/test`.

1. Crie o projeto.

   ```
   gradle build
   ```

1. No diretório raiz do projeto (`/example`), crie um Dockerfile com a seguinte configuração:
   + Defina a propriedade `FROM` como o [URI da imagem base](https://gallery.ecr.aws/lambda/java).
   + Use o comando COPY para copiar o código da função e as dependências do runtime para `{LAMBDA_TASK_ROOT}`, uma [variável de ambiente definida pelo Lambda](configuration-envvars.md#configuration-envvars-runtime).
   + Defina o argumento `CMD` como o manipulador de funções do Lambda.

   Observe que o Dockerfile de exemplo não inclui uma [instrução USER](https://docs.docker.com/reference/dockerfile/#user). Quando você implanta uma imagem de contêiner no Lambda, o Lambda define automaticamente um usuário padrão do Linux com permissões de privilégio mínimo. Isso é diferente do comportamento padrão do Docker, que adota o usuário `root` como padrão quando nenhuma instrução `USER` é fornecida.  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/java:21
     
   # 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" ]
   ```

1. Crie a imagem do Docker com o comando [docker build](https://docs.docker.com/engine/reference/commandline/build/). O exemplo a seguir nomeia a imagem como `docker-image` e atribui a ela a [tag](https://docs.docker.com/engine/reference/commandline/build/#tag) `test`. Para tornar sua imagem compatível com o Lambda, é necessário usar a opção `--provenance=false`.

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**nota**  
O comando especifica a opção `--platform linux/amd64` para garantir que seu contêiner seja compatível com o ambiente de execução do Lambda, independentemente da arquitetura da sua máquina de compilação. Se você pretende criar uma função do Lambda usando a arquitetura do conjunto de instruções ARM64, certifique-se de alterar o comando para usar a opção `--platform linux/arm64` em vez disso.

------

### (Opcional) Teste a imagem localmente
<a name="java-image-test"></a>

1. Inicie a imagem do Docker com o comando **docker run**. Neste exemplo, `docker-image` é o nome da imagem e `test` é a tag.

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   Esse comando executa a imagem como um contêiner e cria um endpoint local em `localhost:9000/2015-03-31/functions/function/invocations`.
**nota**  
Se você criou a imagem do Docker para a arquitetura do conjunto de instruções ARM64, certifique-se de usar a opção `--platform linux/arm64`, em vez de `--platform linux/amd64`.

1. Em uma nova janela de terminal, publique um evento no endpoint local.

------
#### [ Linux/macOS ]

   No Linux e no MacOS, execute o seguinte comando `curl`:

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

   Esse comando invoca a função com um evento vazio e retorna uma resposta. Caso esteja usando seu próprio código de função em vez do código de função de exemplo, você talvez queira invocar a função com uma carga útil JSON. Exemplo:

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   No PowerShell, execute o seguinte comando `Invoke-WebRequest`:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   Esse comando invoca a função com um evento vazio e retorna uma resposta. Caso esteja usando seu próprio código de função em vez do código de função de exemplo, você talvez queira invocar a função com uma carga útil JSON. Exemplo:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. Obtenha o ID do contêiner.

   ```
   docker ps
   ```

1. Use o comando [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) para parar o contêiner. Nesse comando, substitua `3766c4ab331c` pelo ID do contêiner da etapa anterior.

   ```
   docker kill 3766c4ab331c
   ```

### Implantação da imagem
<a name="java-image-deploy"></a>

**Para enviar a imagem ao Amazon ECR e criar a função do Lambda**

1. Execute o comando [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) para autenticar a CLI do Docker no seu registro do Amazon ECR.
   + Defina o valor `--region` para a Região da AWS onde você deseja criar o repositório do Amazon ECR.
   + Substituir `111122223333` por seu ID da Conta da AWS.

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. Crie um repositório no Amazon ECR usando o comando [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html).

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**nota**  
O repositório do Amazon ECR deve estar na mesma Região da AWS que a função do Lambda.

   Se tiver êxito, você verá uma resposta como esta:

   ```
   {
       "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"
           }
       }
   }
   ```

1. Copie o `repositoryUri` da saída na etapa anterior.

1. Execute o comando [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) para aplicar uma tag na sua imagem local em seu repositório do Amazon ECR como a versão mais recente. Neste comando:
   + `docker-image:test` é o nome e a [tag](https://docs.docker.com/engine/reference/commandline/build/#tag) da sua imagem do Docker. Esse é o nome e a tag da imagem que você especificou no comando `docker build`.
   + Substitua `<ECRrepositoryUri>` pelo `repositoryUri` que você copiou. Certifique-se de incluir `:latest` no final do URI.

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   Exemplo:

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. Execute o comando [docker push](https://docs.docker.com/engine/reference/commandline/push/) para implantar a imagem local no repositório do Amazon ECR. Certifique-se de incluir `:latest` no final do URI do repositório.

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [Crie um perfil de execução](lambda-intro-execution-role.md#permissions-executionrole-api) para a função, caso ainda não tenha um. Você precisará do nome do recurso da Amazon (ARN) do perfil na próxima etapa.

1. Criar a função do Lambda. Em `ImageUri`, especifique o URI do repositório anterior. Certifique-se de incluir `:latest` no final do 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
   ```
**nota**  
É possível criar uma função usando uma imagem em uma conta da AWS diferente desde que a imagem esteja na mesma região da função do Lambda. Para obter mais informações, consulte [Permissões entre contas do Amazon ECR](images-create.md#configuration-images-xaccount-permissions).

1. Invoque a função.

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

   Você obterá uma resposta parecida com esta:

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. Para ver a saída da função, verifique o arquivo `response.json`.

Para atualizar o código da função, você deve criar a imagem novamente, fazer upload da nova imagem no repositório do Amazon ECR e, em seguida, usar o comando [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) para implantar a imagem na função do Lambda.

O Lambda resolve a tag de imagem em um resumo de imagem específico. Isso significa que, se você apontar a tag de imagem que foi usada para implantar a função em uma nova imagem no Amazon ECR, o Lambda não atualizará automaticamente a função para usar a nova imagem.

Para implantar a nova imagem na mesma função do Lambda, você deverá usar o comando [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html), mesmo que a tag da imagem no Amazon ECR permaneça a mesma. No exemplo a seguir, a opção `--publish` cria uma nova versão da função usando a imagem de contêiner atualizada.

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

## Usar uma imagem base alternativa com o cliente da interface de runtime
<a name="java-image-clients"></a>

Se você usar uma [imagem base somente para sistema operacional](images-create.md#runtimes-images-provided) ou uma imagem base alternativa, deverá incluir o cliente de interface de runtime na imagem. O cliente de interface de runtime estende [API de runtime](runtimes-api.md), que gerencia a interação entre o Lambda e o código da sua função.

Instale o cliente de interface de runtime para Java no Dockerfile ou como uma dependência no projeto. Por exemplo, para instalar o cliente de interface de runtime usando o gerenciador de pacotes Maven, adicione o seguinte ao seu arquivo `pom.xml`:

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

Para obter detalhes do pacote, consulte [Cliente de interface de runtime do AWS Lambda em Java](https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-runtime-interface-client) no Repositório central do Maven. Também é possível revisar o código-fonte do cliente de interface de runtime no repositório de [Bibliotecas de suporte do Java do AWS Lambda](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-runtime-interface-client) no GitHub.

O exemplo a seguir demonstra como criar uma imagem de contêiner para Java usando uma [imagem do Amazon Corretto](https://gallery.ecr.aws/amazoncorretto/amazoncorretto). O Amazon Corretto é uma distribuição gratuita, multiplataforma e pronta para produção do Open Java Development Kit (OpenJDK). O projeto do Maven inclui o cliente de interface de runtime como uma dependência.

### Pré-requisitos
<a name="java-alt-prerequisites"></a>

Para executar as etapas desta seção, você deve ter o seguinte:
+ Java (por exemplo, [Amazon Corretto](https://aws.amazon.com/corretto))
+ [Apache Maven](https://maven.apache.org/)
+ [AWS CLI versão 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (versão mínima 25.0.0)
+ O plug-in [buildx](https://github.com/docker/buildx/blob/master/README.md) do Docker.

### Criar uma imagem de uma imagem base alternativa
<a name="java-alt-create"></a>

1. Criar um projeto do Maven. Os seguintes parâmetros são obrigatórios:
   + **groupId**: o namespace completo do pacote da sua aplicação.
   + **artifactId**: o nome do seu projeto. Esse será o nome do diretório do projeto.

------
#### [ Linux/macOS ]

   ```
   mvn -B archetype:generate \
      -DarchetypeArtifactId=maven-archetype-quickstart \
      -DgroupId=example \
      -DartifactId=myapp \
      -DinteractiveMode=false
   ```

------
#### [ PowerShell ]

   ```
   mvn -B archetype:generate `
      -DarchetypeArtifactId=maven-archetype-quickstart `
      -DgroupId=example `
      -DartifactId=myapp `
      -DinteractiveMode=false
   ```

------

1. Abra o diretório do projeto.

   ```
   cd myapp
   ```

1. Abra o arquivo `pom.xml` e substitua o conteúdo pelo seguinte. Esse arquivo inclui o [aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-runtime-interface-client) como uma dependência. Como alternativa, você também pode instalar o cliente de interface de runtime no Dockerfile. No entanto, a abordagem mais simples é incluir a biblioteca como uma dependência.

   ```
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>example</groupId>
     <artifactId>hello-lambda</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>hello-lambda</name>
     <url>http://maven.apache.org</url>
     <properties>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
     <dependencies>
       <dependency>
         <groupId>com.amazonaws</groupId>
         <artifactId>aws-lambda-java-runtime-interface-client</artifactId>
         <version>2.3.2</version>
       </dependency>
     </dependencies>
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-dependency-plugin</artifactId>
           <version>3.1.2</version>
           <executions>
             <execution>
               <id>copy-dependencies</id>
               <phase>package</phase>
               <goals>
                 <goal>copy-dependencies</goal>
               </goals>
             </execution>
           </executions>
         </plugin>
       </plugins>
     </build>
   </project>
   ```

1. Abra o diretório `myapp/src/main/java/com/example/myapp` e localize o arquivo `App.java`. Este é o código da função do Lambda. Substitua o código pelo seguinte.  
**Example manipulador de função**  

   ```
   package example;
   
   public class App {
       public static String sayHello() {
           return "Hello world!";
       }
   }
   ```

1. O comando `mvn -B archetype:generate` da etapa 1 também gerou um caso de teste fictício no diretório `src/test`. Para fins deste tutorial, pule a execução de testes excluindo todo este diretório `/test` gerado.

1. Navegue de volta para o diretório raiz do projeto e, em seguida, crie um Dockerfile. O Dockerfile do exemplo a seguir usa uma [imagem do Amazon Corretto](https://gallery.ecr.aws/amazoncorretto/amazoncorretto). O Amazon Corretto é uma distribuição gratuita, multiplataforma e pronta para produção do OpenJDK.
   + Defina a propriedade `FROM` como o URI da imagem base.
   + Defina o `ENTRYPOINT` como o módulo em que você deseja que o contêiner do Docker seja executado quando for iniciado. Nesse caso, o módulo é o cliente de interface de runtime.
   + Defina o argumento `CMD` como o manipulador de funções do Lambda.

   Observe que o Dockerfile de exemplo não inclui uma [instrução USER](https://docs.docker.com/reference/dockerfile/#user). Quando você implanta uma imagem de contêiner no Lambda, o Lambda define automaticamente um usuário padrão do Linux com permissões de privilégio mínimo. Isso é diferente do comportamento padrão do Docker, que adota o usuário `root` como padrão quando nenhuma instrução `USER` é fornecida.  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/amazoncorretto/amazoncorretto:21 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 ./
   
   # Set runtime interface client as default command for the container runtime
   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
   CMD [ "example.App::sayHello" ]
   ```

1. Crie a imagem do Docker com o comando [docker build](https://docs.docker.com/engine/reference/commandline/build/). O exemplo a seguir nomeia a imagem como `docker-image` e atribui a ela a [tag](https://docs.docker.com/engine/reference/commandline/build/#tag) `test`. Para tornar sua imagem compatível com o Lambda, é necessário usar a opção `--provenance=false`.

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**nota**  
O comando especifica a opção `--platform linux/amd64` para garantir que seu contêiner seja compatível com o ambiente de execução do Lambda, independentemente da arquitetura da sua máquina de compilação. Se você pretende criar uma função do Lambda usando a arquitetura do conjunto de instruções ARM64, certifique-se de alterar o comando para usar a opção `--platform linux/arm64` em vez disso.

### (Opcional) Teste a imagem localmente
<a name="java-alt-test"></a>

Use o [emulador de interface de runtime](https://github.com/aws/aws-lambda-runtime-interface-emulator/) para testar a imagem localmente. É possível [compilar o emulador em sua imagem](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image) ou usar o procedimento a seguir instalá-lo na sua máquina local.

**Para instalar o emulador de interface de runtime na sua máquina local**

1. No diretório do projeto, execute o comando a seguir para baixar o emulador de interface de runtime (arquitetura x86-64) do GitHub e instalá-lo na sua máquina local.

------
#### [ Linux/macOS ]

   ```
   mkdir -p ~/.aws-lambda-rie && \
       curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
       chmod +x ~/.aws-lambda-rie/aws-lambda-rie
   ```

   Para instalar o emulador arm64, substitua o URL do repositório do GitHub no comando anterior pelo seguinte:

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------
#### [ PowerShell ]

   ```
   $dirPath = "$HOME\.aws-lambda-rie"
   if (-not (Test-Path $dirPath)) {
       New-Item -Path $dirPath -ItemType Directory
   }
         
   $downloadLink = "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie"
   $destinationPath = "$HOME\.aws-lambda-rie\aws-lambda-rie"
   Invoke-WebRequest -Uri $downloadLink -OutFile $destinationPath
   ```

   Para instalar o emulador de arm64, substitua `$downloadLink` pelo seguinte:

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------

1. Inicie a imagem do Docker com o comando **docker run**. Observe o seguinte:
   + `docker-image` é o nome da imagem e `test` é a tag.
   + `/usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello` é o `ENTRYPOINT` seguido pelo `CMD` do Dockerfile.

------
#### [ Linux/macOS ]

   ```
   docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
       --entrypoint /aws-lambda/aws-lambda-rie \
       docker-image:test \
           /usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello
   ```

------
#### [ PowerShell ]

   ```
   docker run --platform linux/amd64 -d -v "$HOME\.aws-lambda-rie:/aws-lambda" -p 9000:8080 `
   --entrypoint /aws-lambda/aws-lambda-rie `
   docker-image:test `
       /usr/bin/java -cp './*' com.amazonaws.services.lambda.runtime.api.client.AWSLambda example.App::sayHello
   ```

------

   Esse comando executa a imagem como um contêiner e cria um endpoint local em `localhost:9000/2015-03-31/functions/function/invocations`.
**nota**  
Se você criou a imagem do Docker para a arquitetura do conjunto de instruções ARM64, certifique-se de usar a opção `--platform linux/arm64`, em vez de `--platform linux/amd64`.

1. Publique um evento no endpoint local.

------
#### [ Linux/macOS ]

   No Linux e no MacOS, execute o seguinte comando `curl`:

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

   Esse comando invoca a função com um evento vazio e retorna uma resposta. Caso esteja usando seu próprio código de função em vez do código de função de exemplo, você talvez queira invocar a função com uma carga útil JSON. Exemplo:

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   No PowerShell, execute o seguinte comando `Invoke-WebRequest`:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   Esse comando invoca a função com um evento vazio e retorna uma resposta. Caso esteja usando seu próprio código de função em vez do código de função de exemplo, você talvez queira invocar a função com uma carga útil JSON. Exemplo:

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. Obtenha o ID do contêiner.

   ```
   docker ps
   ```

1. Use o comando [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) para parar o contêiner. Nesse comando, substitua `3766c4ab331c` pelo ID do contêiner da etapa anterior.

   ```
   docker kill 3766c4ab331c
   ```

### Implantação da imagem
<a name="java-alt-deploy"></a>

**Para enviar a imagem ao Amazon ECR e criar a função do Lambda**

1. Execute o comando [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) para autenticar a CLI do Docker no seu registro do Amazon ECR.
   + Defina o valor `--region` para a Região da AWS onde você deseja criar o repositório do Amazon ECR.
   + Substituir `111122223333` por seu ID da Conta da AWS.

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. Crie um repositório no Amazon ECR usando o comando [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html).

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**nota**  
O repositório do Amazon ECR deve estar na mesma Região da AWS que a função do Lambda.

   Se tiver êxito, você verá uma resposta como esta:

   ```
   {
       "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"
           }
       }
   }
   ```

1. Copie o `repositoryUri` da saída na etapa anterior.

1. Execute o comando [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) para aplicar uma tag na sua imagem local em seu repositório do Amazon ECR como a versão mais recente. Neste comando:
   + `docker-image:test` é o nome e a [tag](https://docs.docker.com/engine/reference/commandline/build/#tag) da sua imagem do Docker. Esse é o nome e a tag da imagem que você especificou no comando `docker build`.
   + Substitua `<ECRrepositoryUri>` pelo `repositoryUri` que você copiou. Certifique-se de incluir `:latest` no final do URI.

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   Exemplo:

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. Execute o comando [docker push](https://docs.docker.com/engine/reference/commandline/push/) para implantar a imagem local no repositório do Amazon ECR. Certifique-se de incluir `:latest` no final do URI do repositório.

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [Crie um perfil de execução](lambda-intro-execution-role.md#permissions-executionrole-api) para a função, caso ainda não tenha um. Você precisará do nome do recurso da Amazon (ARN) do perfil na próxima etapa.

1. Criar a função do Lambda. Em `ImageUri`, especifique o URI do repositório anterior. Certifique-se de incluir `:latest` no final do 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
   ```
**nota**  
É possível criar uma função usando uma imagem em uma conta da AWS diferente desde que a imagem esteja na mesma região da função do Lambda. Para obter mais informações, consulte [Permissões entre contas do Amazon ECR](images-create.md#configuration-images-xaccount-permissions).

1. Invoque a função.

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

   Você obterá uma resposta parecida com esta:

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. Para ver a saída da função, verifique o arquivo `response.json`.

Para atualizar o código da função, você deve criar a imagem novamente, fazer upload da nova imagem no repositório do Amazon ECR e, em seguida, usar o comando [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) para implantar a imagem na função do Lambda.

O Lambda resolve a tag de imagem em um resumo de imagem específico. Isso significa que, se você apontar a tag de imagem que foi usada para implantar a função em uma nova imagem no Amazon ECR, o Lambda não atualizará automaticamente a função para usar a nova imagem.

Para implantar a nova imagem na mesma função do Lambda, você deverá usar o comando [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html), mesmo que a tag da imagem no Amazon ECR permaneça a mesma. No exemplo a seguir, a opção `--publish` cria uma nova versão da função usando a imagem de contêiner atualizada.

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```