Implantar funções do Lambda em Ruby com imagens de contêiner - AWS Lambda

Implantar funções do Lambda em Ruby com imagens de contêiner

Existem três maneiras de criar uma imagem de contêiner para uma função do Lambda em Ruby:

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 na documentação do Docker. Para criar imagens de contêiner eficientes, siga as Melhores práticas para gravar Dockerfiles.

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

Imagens base da AWS para Ruby

A AWS oferece as seguintes imagens base para Ruby:

Tags Runtime Sistema operacional Dockerfile Desaprovação

3.3

Ruby 3.3 Amazon Linux 2023 Dockerfile para Ruby 3.3 no GitHub

3.2

Ruby 3.2 Amazon Linux 2 Dockerfile para Ruby 3.2 no GitHub

Repositório do Amazon ECR: gallery.ecr.aws/lambda/ruby

Usar uma imagem base da AWS para Ruby

Para executar as etapas desta seção, você deve ter o seguinte:

Para criar uma imagem de contêiner para Ruby
  1. Crie um diretório para o projeto e depois mude para esse diretório.

    mkdir example cd example
  2. Crie um novo arquivo chamado Gemfile. É aqui que você lista os pacotes do RubyGems necessários da sua aplicação. O AWS SDK for Ruby está disponível no RubyGems. Você deve escolher gems de serviço da AWS específicos para instalar. Por exemplo, para usar o gem do Ruby para Lambda, seu Gemfile deve ser:

    source 'https://rubygems.org' gem 'aws-sdk-lambda'

    Como alternativa, o gem aws-sdk contém todos os gems de serviço da AWS disponíveis. Esse gem é muito grande. Recomendamos que ele só seja usado se você depender de muitos serviços da AWS.

  3. Instale as dependências especificadas no Gemfile usando instalação de pacote.

    bundle install
  4. Crie um novo arquivo chamado lambda_function.rb. É possível adicionar o exemplo de código de função a seguir ao arquivo para testes ou usar o seu próprio código.

    exemplo Função Ruby
    module LambdaFunction class Handler def self.process(event:,context:) "Hello from Lambda!" end end end
  5. Crie um novo Dockerfile. É mostrado a seguir um exemplo de Dockerfile que usa uma imagem base da AWS. Esse Dockerfile usa a seguinte configuração:

    • Defina a propriedade FROM como o URI da imagem base.

    • 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.

    • 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. 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.

    exemplo Dockerfile
    FROM public.ecr.aws/lambda/ruby:3.2 # Copy Gemfile and Gemfile.lock COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/ # Install Bundler and the specified gems RUN gem install bundler:2.4.20 && \ bundle config set --local path 'vendor/bundle' && \ bundle install # Copy function code COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/ # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "lambda_function.LambdaFunction::Handler.process" ]
  6. Crie a imagem do Docker com o comando docker build. O exemplo a seguir nomeia a imagem como docker-image e atribui a ela a tag test.

    docker build --platform linux/amd64 -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.

  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.

  2. 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"
  3. Obtenha o ID do contêiner.

    docker ps
  4. Use o comando docker kill para parar o contêiner. Nesse comando, substitua 3766c4ab331c pelo ID do contêiner da etapa anterior.

    docker kill 3766c4ab331c
Para enviar a imagem ao Amazon ECR e criar a função do Lambda
  1. Execute o comando get-login-password 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
  2. Crie um repositório no Amazon ECR usando o comando create-repository.

    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" } } }
  3. Copie o repositoryUri da saída na etapa anterior.

  4. Execute o comando docker 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 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
  5. Execute o comando docker 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
  6. Crie um perfil de execução 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.

  7. 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 ter mais informações, consulte Permissões entre contas do Amazon ECR.

  8. Invoque a função.

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

    Você obterá uma resposta parecida com esta:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. 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 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, 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

Se você usar uma imagem base somente para sistema operacional ou uma imagem base alternativa, deverá incluir o cliente de interface de runtime na imagem. O cliente de interface de runtime estende Usar a API de runtime do Lambda para runtimes personalizados, que gerencia a interação entre o Lambda e o código da sua função.

Instale o cliente de interface de runtime para Ruby usando o gerenciador de pacotes RubyGems.org:

gem install aws_lambda_ric

Você também pode fazer download do cliente de interface de runtime do Ruby no GitHub. O cliente da interface de runtime é compatível com as versões 2.5.x a 2.7.x do Ruby.

O exemplo a seguir demonstra como criar uma imagem de contêiner para Ruby usando uma imagem base que não é da AWS. O exemplo de Dockerfile usa uma imagem base oficial do Ruby. O Dockerfile inclui o cliente de interface de runtime.

Para executar as etapas desta seção, você deve ter o seguinte:

Para criar uma imagem de contêiner usando uma imagem base alternativa do Ruby
  1. Crie um diretório para o projeto e depois mude para esse diretório.

    mkdir example cd example
  2. Crie um novo arquivo chamado Gemfile. É aqui que você lista os pacotes do RubyGems necessários da sua aplicação. O AWS SDK for Ruby está disponível no RubyGems. Você deve escolher gems de serviço da AWS específicos para instalar. Por exemplo, para usar o gem do Ruby para Lambda, seu Gemfile deve ser:

    source 'https://rubygems.org' gem 'aws-sdk-lambda'

    Como alternativa, o gem aws-sdk contém todos os gems de serviço da AWS disponíveis. Esse gem é muito grande. Recomendamos que ele só seja usado se você depender de muitos serviços da AWS.

  3. Instale as dependências especificadas no Gemfile usando instalação de pacote.

    bundle install
  4. Crie um novo arquivo chamado lambda_function.rb. É possível adicionar o exemplo de código de função a seguir ao arquivo para testes ou usar o seu próprio código.

    exemplo Função Ruby
    module LambdaFunction class Handler def self.process(event:,context:) "Hello from Lambda!" end end end
  5. Crie um novo Dockerfile. O Dockerfile a seguir usa uma imagem base do Ruby em vez de uma imagem base da AWS. O Dockerfile inclui o cliente de interface de runtime do Ruby, o que torna a imagem compatível com o Lambda. Como alternativa, você pode adicionar o cliente da interface de runtime ao Gemfile da aplicação.

    • Defina a propriedade FROM como a imagem básica do Ruby.

    • Crie um diretório para o código da função e uma variável de ambiente que aponte para esse diretório. Neste exemplo, o diretório é /var/task, que espelha o ambiente de execução do Lambda. No entanto, você pode escolher qualquer diretório para o código da função, pois o Dockerfile não usa uma imagem básica da AWS.

    • 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. 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.

    exemplo Dockerfile
    FROM ruby:2.7 # Install the runtime interface client for Ruby RUN gem install aws_lambda_ric # Add the runtime interface client to the PATH ENV PATH="/usr/local/bundle/bin:${PATH}" # Create a directory for the Lambda function ENV LAMBDA_TASK_ROOT=/var/task RUN mkdir -p ${LAMBDA_TASK_ROOT} WORKDIR ${LAMBDA_TASK_ROOT} # Copy Gemfile and Gemfile.lock COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/ # Install Bundler and the specified gems RUN gem install bundler:2.4.20 && \ bundle config set --local path 'vendor/bundle' && \ bundle install # Copy function code COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/ # Set runtime interface client as default command for the container runtime ENTRYPOINT [ "aws_lambda_ric" ] # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "lambda_function.LambdaFunction::Handler.process" ]
  6. Crie a imagem do Docker com o comando docker build. O exemplo a seguir nomeia a imagem como docker-image e atribui a ela a tag test.

    docker build --platform linux/amd64 -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.

Use o emulador de interface de runtime para testar a imagem localmente. Você pode compilar o emulador em sua imagem 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
  2. Inicie a imagem do Docker com o comando docker run. Observe o seguinte:

    • docker-image é o nome da imagem e test é a tag.

    • aws_lambda_ric lambda_function.LambdaFunction::Handler.process é 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 \ aws_lambda_ric lambda_function.LambdaFunction::Handler.process
    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 ` aws_lambda_ric lambda_function.LambdaFunction::Handler.process

    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.

  3. 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"
  4. Obtenha o ID do contêiner.

    docker ps
  5. Use o comando docker kill para parar o contêiner. Nesse comando, substitua 3766c4ab331c pelo ID do contêiner da etapa anterior.

    docker kill 3766c4ab331c
Para enviar a imagem ao Amazon ECR e criar a função do Lambda
  1. Execute o comando get-login-password 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
  2. Crie um repositório no Amazon ECR usando o comando create-repository.

    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" } } }
  3. Copie o repositoryUri da saída na etapa anterior.

  4. Execute o comando docker 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 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
  5. Execute o comando docker 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
  6. Crie um perfil de execução 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.

  7. 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 ter mais informações, consulte Permissões entre contas do Amazon ECR.

  8. Invoque a função.

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

    Você obterá uma resposta parecida com esta:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. 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 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, 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