Implemente funciones Go Lambda con imágenes de contenedor - AWS Lambda

Implemente funciones Go Lambda con imágenes de contenedor

Hay dos formas de compilar una imagen de contenedor para una función de Lambda en Go:

  • Uso de una imagen base exclusiva del sistema operativo de AWS

    Go se implementa de manera distinta a otros tiempos de ejecución administrados. Como Go se compila de forma nativa en un archivo binario ejecutable, no requiere un tiempo de ejecución de lenguaje dedicado. Utilice una imagen base exclusiva para el sistema operativo para crear imágenes de Go para Lambda. Para que la imagen sea compatible con Lambda, debe incluir el paquete aws-lambda-go/lambda en la imagen.

  • Uso de una imagen base que no sea de AWS

    Puede utilizar una imagen base alternativa de otro registro de contenedores, como Alpine Linux o Debian. También puede utilizar una imagen personalizada creada por su organización. Para que la imagen sea compatible con Lambda, debe incluir el paquete aws-lambda-go/lambda en la imagen.

sugerencia

Para reducir el tiempo que tardan las funciones de contenedor de Lambda en activarse, consulte Uso de compilaciones de varias fases en la documentación de Docker. Para compilar imágenes de contenedores eficientes, siga Prácticas recomendadas para escribir Dockerfiles.

En esta página, se explica cómo compilar, probar e implementar imágenes de contenedor para Lambda.

Imágenes base de AWS para implementar funciones de Go

Go se implementa de manera distinta a otros tiempos de ejecución administrados. Como Go se compila de forma nativa en un archivo binario ejecutable, no requiere un tiempo de ejecución de lenguaje dedicado. Utilice una imagen base exclusiva para el sistema operativo para implementar funciones de Go en Lambda.

Nombre Identificador Sistema operativo Fecha de baja Bloqueo de la función Crear Bloqueo de la función Actualizar

Tiempo de ejecución exclusivo del sistema operativo

provided.al2023

Amazon Linux 2023

No programado

No programado

No programado

Tiempo de ejecución exclusivo del sistema operativo

provided.al2

Amazon Linux 2

No programado

No programado

No programado

Galería pública de Amazon Elastic Container Registry: gallery.ecr.aws/lambda/provided

Cliente de interfaz de tiempo de ejecución de Go

El paquete aws-lambda-go/lambda incluye una implementación de la interfaz de tiempo de ejecución. Para ver ejemplos de cómo usar aws-lambda-go/lambda en la imagen, consulte Uso de una imagen base exclusiva del sistema operativo de AWS o Uso de una imagen base que no sea de AWS.

Uso de una imagen base exclusiva del sistema operativo de AWS

Go se implementa de manera distinta a otros tiempos de ejecución administrados. Como Go se compila de forma nativa en un archivo binario ejecutable, no requiere un tiempo de ejecución de lenguaje dedicado. Utilice una imagen base exclusiva para el sistema operativo para compilar imágenes de contenedor para funciones de Go.

Etiquetas Tiempo de ejecución Sistema operativo Dockerfile Obsolescencia

al2023

Tiempo de ejecución exclusivo del sistema operativo Amazon Linux 2023 Dockerfile para tiempo de ejecución exclusivo del sistema operativo en GitHub

No programado

al2

Tiempo de ejecución exclusivo del sistema operativo Amazon Linux 2 Dockerfile para tiempo de ejecución exclusivo del sistema operativo en GitHub

No programado

Para obtener más información acerca de estas imágenes base, consulte provided en la galería pública de Amazon ECR.

Debe incluir el paquete aws-lambda-go/lambda con su controlador de Go. Este paquete implementa el modelo de programación para Go, incluida la interfaz de tiempo de ejecución.

Para completar los pasos de esta sección, debe disponer de lo siguiente:

Para compilar e implementar una función de Go con la imagen base de provided.al2023
  1. Cree un directorio para el proyecto y, a continuación, cambie a ese directorio.

    mkdir hello cd hello
  2. Inicialice un nuevo módulo de Go.

    go mod init example.com/hello-world
  3. Agregue la biblioteca lambda como dependencia de su nuevo módulo.

    go get github.com/aws/aws-lambda-go/lambda
  4. Cree un archivo con el nombre main.go y, a continuación, ábralo en un editor de texto. Se trata del código de la función de Lambda. Puede utilizar el siguiente código de muestra para realizar pruebas o sustituirlo por su propio código.

    package main import ( "context" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { response := events.APIGatewayProxyResponse{ StatusCode: 200, Body: "\"Hello from Lambda!\"", } return response, nil } func main() { lambda.Start(handler) }
  5. Utilice un editor de texto para crear un Dockerfile en el directorio del proyecto.

    • El siguiente Dockerfile de ejemplo utiliza una compilación de varias etapas. Esto le permite utilizar una imagen base diferente en cada paso. Puede usar una imagen, como una imagen base de Go, para compilar el código y crear el binario ejecutable. Luego puede utilizar una imagen diferente, como provided.al2023, en la instrucción final FROM para definir la imagen que va a implementar en Lambda. El proceso de compilación está separado de la imagen de implementación final, por lo que la imagen final solo contiene los archivos necesarios para ejecutar la aplicación.

    • Puede utilizar la etiqueta opcional lambda.norpc para excluir el componente de llamada a procedimiento remoto (RPC) de la biblioteca lambda. El componente de RPC solo es necesario si utiliza el tiempo de ejecución obsoleto Go 1.x. La exclusión del RPC reduce el tamaño del paquete de implementación.

    • Tenga en cuenta que el Dockerfile de ejemplo no incluye una instrucción USER. Al implementar una imagen de contenedor en Lambda, Lambda define automáticamente un usuario predeterminado de Linux con permisos de privilegio mínimo. Esto es diferente del comportamiento estándar de Docker, que utiliza de forma predeterminada el usuario root cuando no se proporciona ninguna instrucción USER.

    ejemplo — Dockerfile de compilación de varias etapas
    nota

    Asegúrese de que la versión de Go que especifique en su Dockerfile (por ejemplo, golang:1.20) sea la misma versión de Go que utilizó para crear su aplicación.

    FROM golang:1.20 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # Build with optional lambda.norpc tag COPY main.go . RUN go build -tags lambda.norpc -o main main.go # Copy artifacts to a clean image FROM public.ecr.aws/lambda/provided:al2023 COPY --from=build /helloworld/main ./main ENTRYPOINT [ "./main" ]
  6. Compile la imagen de Docker con el comando docker build. En el siguiente ejemplo se asigna un nombre a la imagen docker-image y se le asigna la etiqueta test.

    docker build --platform linux/amd64 -t docker-image:test .
    nota

    El comando especifica la opción --platform linux/amd64 para garantizar que el contenedor sea compatible con el entorno de ejecución de Lambda, independientemente de la arquitectura de la máquina de compilación. Si tiene intención de crear una función de Lambda con la arquitectura del conjunto de instrucciones ARM64, asegúrese de cambiar el comando para utilizar la opción --platform linux/arm64 en su lugar.

Utilice el emulador de interfaz de tiempo de ejecución para probar la imagen localmente. El emulador de interfaz de tiempo de ejecución se incluye en la imagen base de provided.al2023.

Para ejecutar el emulador de interfaz de tiempo de ejecución en su equipo local
  1. Inicie la imagen de Docker con el comando docker run. Tenga en cuenta lo siguiente:

    • docker-image es el nombre de la imagen y test es la etiqueta.

    • ./main es el ENTRYPOINT de su Dockerfile.

    docker run -d -p 9000:8080 \ --entrypoint /usr/local/bin/aws-lambda-rie \ docker-image:test ./main

    Este comando ejecuta la imagen como un contenedor y crea un punto de conexión local en localhost:9000/2015-03-31/functions/function/invocations.

  2. Desde una nueva ventana de terminal, publique un evento en el siguiente punto de conexión mediante un comando curl:

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

    Este comando invoca la función con un evento vacío y devuelve una respuesta. Es posible que algunas funciones requieran una carga JSON. Ejemplo:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
  3. Obtenga el ID del contenedor.

    docker ps
  4. Use el comando docker kill para detener el contenedor. En este comando, reemplace 3766c4ab331c por el ID del contenedor del paso anterior.

    docker kill 3766c4ab331c
Para cargar la imagen en Amazon ECR y crear la función de Lambda
  1. Para autenticar la CLI de Docker en su registro de Amazon ECR, ejecute el comando get-login-password.

    • Establezca el valor de --region en la Región de AWS en la que desee crear el repositorio de Amazon ECR.

    • Reemplace 111122223333 por el ID de su Cuenta de 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. Cree un repositorio en Amazon ECR con el 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

    El repositorio de Amazon ECR debe estar en la misma Región de AWS que la función de Lambda.

    Si se realiza de la forma correcta, verá una respuesta como la siguiente:

    { "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 el valor de repositoryUri de la salida del paso anterior.

  4. Ejecute el comando docker tag para etiquetar la imagen local en su repositorio de Amazon ECR como la versión más reciente. En este comando:

    • docker-image:test es el nombre y la etiqueta de su imagen de Docker. Son el nombre y la etiqueta de la imagen que especificó en el comando docker build.

    • Reemplace <ECRrepositoryUri> por el repositoryUri que ha copiado. Asegúrese de incluir :latest al final del URI.

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

    Ejemplo:

    docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  5. Ejecute el comando docker push para implementar la imagen local en el repositorio de Amazon ECR. Asegúrese de incluir :latest al final del URI del repositorio.

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. Cree un rol de ejecución para la función si aún no tiene uno. Necesitará el nombre de recurso de Amazon (ARN) del rol en el paso siguiente.

  7. Cree la función de Lambda. En ImageUri, especifique el URI del repositorio anterior. Asegúrese de incluir :latest al final del 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

    Puede crear una función con una imagen de una cuenta AWS diferente, siempre que la imagen esté en la misma región que la función de Lambda. Para obtener más información, consulte Permisos entre cuentas de Amazon ECR.

  8. Invoque la función.

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

    Debería ver una respuesta como la siguiente:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. Para ver la salida de la función, compruebe el archivo response.json.

Para actualizar el código de la función, debe volver a compilar la imagen, cargar la nueva imagen en el repositorio de Amazon ECR y, a continuación, utilizar el comando update-function-code para implementar la imagen en la función de Lambda.

Lambda resuelve la etiqueta de la imagen en un resumen de imagen específico. Esto significa que si apunta la etiqueta de imagen que se utilizó para implementar la función a una nueva imagen en Amazon ECR, Lambda no actualiza automáticamente la función para usar la nueva imagen.

Para implementar la nueva imagen en la misma función de Lambda, debe usar el comando update-function-code, incluso si la etiqueta de la imagen en Amazon ECR sigue siendo la misma. En el siguiente ejemplo, la opción --publish crea una nueva versión de la función con la imagen del contenedor actualizada.

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

Uso de una imagen base que no sea de AWS

Puede crear una imagen de contenedor para Go a partir de una imagen base que no es de AWS. El Dockerfile de ejemplo en los siguientes pasos usa una imagen base de Alpine.

Debe incluir el paquete aws-lambda-go/lambda con su controlador de Go. Este paquete implementa el modelo de programación para Go, incluida la interfaz de tiempo de ejecución.

Para completar los pasos de esta sección, debe disponer de lo siguiente:

Para crear e implementar una función de Go con una imagen base de Alpine
  1. Cree un directorio para el proyecto y, a continuación, cambie a ese directorio.

    mkdir hello cd hello
  2. Inicialice un nuevo módulo de Go.

    go mod init example.com/hello-world
  3. Agregue la biblioteca lambda como dependencia de su nuevo módulo.

    go get github.com/aws/aws-lambda-go/lambda
  4. Cree un archivo con el nombre main.go y, a continuación, ábralo en un editor de texto. Se trata del código de la función de Lambda. Puede utilizar el siguiente código de muestra para realizar pruebas o sustituirlo por su propio código.

    package main import ( "context" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func handler(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { response := events.APIGatewayProxyResponse{ StatusCode: 200, Body: "\"Hello from Lambda!\"", } return response, nil } func main() { lambda.Start(handler) }
  5. Utilice un editor de texto para crear un Dockerfile en el directorio del proyecto. El siguiente Dockerfile de ejemplo usa una imagen base de Alpine. Tenga en cuenta que el Dockerfile de ejemplo no incluye una instrucción USER. Al implementar una imagen de contenedor en Lambda, Lambda define automáticamente un usuario predeterminado de Linux con permisos de privilegio mínimo. Esto es diferente del comportamiento estándar de Docker, que utiliza de forma predeterminada el usuario root cuando no se proporciona ninguna instrucción USER.

    ejemplo Dockerfile
    nota

    Asegúrese de que la versión de Go que especifique en su Dockerfile (por ejemplo, golang:1.20) sea la misma versión de Go que utilizó para crear su aplicación.

    FROM golang:1.20.2-alpine3.16 as build WORKDIR /helloworld # Copy dependencies list COPY go.mod go.sum ./ # Build COPY main.go . RUN go build -o main main.go # Copy artifacts to a clean image FROM alpine:3.16 COPY --from=build /helloworld/main /main ENTRYPOINT [ "/main" ]
  6. Compile la imagen de Docker con el comando docker build. En el siguiente ejemplo se asigna un nombre a la imagen docker-image y se le asigna la etiqueta test.

    docker build --platform linux/amd64 -t docker-image:test .
    nota

    El comando especifica la opción --platform linux/amd64 para garantizar que el contenedor sea compatible con el entorno de ejecución de Lambda, independientemente de la arquitectura de la máquina de compilación. Si tiene intención de crear una función de Lambda con la arquitectura del conjunto de instrucciones ARM64, asegúrese de cambiar el comando para utilizar la opción --platform linux/arm64 en su lugar.

Utilice el emulador de interfaz de tiempo de ejecución para probar la imagen localmente. Puede crear el emulador en su imagen o usar el procedimiento siguiente para instalarlo en su equipo local.

Para instalar y ejecutar el emulador de interfaz de tiempo de ejecución en su equipo local
  1. Desde el directorio del proyecto, ejecute el siguiente comando para descargar el emulador de interfaz de tiempo de ejecución (arquitectura x86-64) de GitHub e instalarlo en su equipo 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 el emulador arm64, reemplace la URL del repositorio de GitHub en el comando anterior por lo siguiente:

    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 el emulador arm64, reemplace el $downloadLink con lo siguiente:

    https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
  2. Inicie la imagen de Docker con el comando docker run. Tenga en cuenta lo siguiente:

    • docker-image es el nombre de la imagen y test es la etiqueta.

    • /main es el ENTRYPOINT de su 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 \ /main
    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 ` /main

    Este comando ejecuta la imagen como un contenedor y crea un punto de conexión local en localhost:9000/2015-03-31/functions/function/invocations.

    nota

    Si creó la imagen de Docker para la arquitectura del conjunto de instrucciones ARM64, asegúrese de utilizar la opción --platform linux/arm64 en lugar de --platform linux/amd64.

  3. Publique un evento en el punto de conexión local.

    Linux/macOS

    En Linux y macOS, ejecute el siguiente comando curl:

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

    Este comando invoca la función con un evento vacío y devuelve una respuesta. Si utiliza su propio código de función en lugar del código de función de ejemplo, quizás quiera invocar la función con una carga JSON. Ejemplo:

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

    En PowerShell, ejecute el siguiente comando Invoke-WebRequest:

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

    Este comando invoca la función con un evento vacío y devuelve una respuesta. Si utiliza su propio código de función en lugar del código de función de ejemplo, quizás quiera invocar la función con una carga JSON. Ejemplo:

    Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
  4. Obtenga el ID del contenedor.

    docker ps
  5. Use el comando docker kill para detener el contenedor. En este comando, reemplace 3766c4ab331c por el ID del contenedor del paso anterior.

    docker kill 3766c4ab331c
Para cargar la imagen en Amazon ECR y crear la función de Lambda
  1. Para autenticar la CLI de Docker en su registro de Amazon ECR, ejecute el comando get-login-password.

    • Establezca el valor de --region en la Región de AWS en la que desee crear el repositorio de Amazon ECR.

    • Reemplace 111122223333 por el ID de su Cuenta de 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. Cree un repositorio en Amazon ECR con el 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

    El repositorio de Amazon ECR debe estar en la misma Región de AWS que la función de Lambda.

    Si se realiza de la forma correcta, verá una respuesta como la siguiente:

    { "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 el valor de repositoryUri de la salida del paso anterior.

  4. Ejecute el comando docker tag para etiquetar la imagen local en su repositorio de Amazon ECR como la versión más reciente. En este comando:

    • docker-image:test es el nombre y la etiqueta de su imagen de Docker. Son el nombre y la etiqueta de la imagen que especificó en el comando docker build.

    • Reemplace <ECRrepositoryUri> por el repositoryUri que ha copiado. Asegúrese de incluir :latest al final del URI.

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

    Ejemplo:

    docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  5. Ejecute el comando docker push para implementar la imagen local en el repositorio de Amazon ECR. Asegúrese de incluir :latest al final del URI del repositorio.

    docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
  6. Cree un rol de ejecución para la función si aún no tiene uno. Necesitará el nombre de recurso de Amazon (ARN) del rol en el paso siguiente.

  7. Cree la función de Lambda. En ImageUri, especifique el URI del repositorio anterior. Asegúrese de incluir :latest al final del 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

    Puede crear una función con una imagen de una cuenta AWS diferente, siempre que la imagen esté en la misma región que la función de Lambda. Para obtener más información, consulte Permisos entre cuentas de Amazon ECR.

  8. Invoque la función.

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

    Debería ver una respuesta como la siguiente:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. Para ver la salida de la función, compruebe el archivo response.json.

Para actualizar el código de la función, debe volver a compilar la imagen, cargar la nueva imagen en el repositorio de Amazon ECR y, a continuación, utilizar el comando update-function-code para implementar la imagen en la función de Lambda.

Lambda resuelve la etiqueta de la imagen en un resumen de imagen específico. Esto significa que si apunta la etiqueta de imagen que se utilizó para implementar la función a una nueva imagen en Amazon ECR, Lambda no actualiza automáticamente la función para usar la nueva imagen.

Para implementar la nueva imagen en la misma función de Lambda, debe usar el comando update-function-code, incluso si la etiqueta de la imagen en Amazon ECR sigue siendo la misma. En el siguiente ejemplo, la opción --publish crea una nueva versión de la función con la imagen del contenedor actualizada.

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