Deploy Go Lambda functions with container images - Amazon Lambda
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Deploy Go Lambda functions with container images

There are three ways to build a container image for a Go Lambda function:

  • Using the provided.al2 Amazon base image

    Go is implemented differently than other managed runtimes. Because Go compiles to native code, Lambda treats Go as a custom runtime. We recommend that you use the provided.al2 base image for custom runtimes to build Go images for Lambda. To make the image compatible with Lambda, you must include the aws-lambda-go/lambda package in the image.

  • Using a non-Amazon base image

    You can use an alternative base image from another container registry, such as Alpine Linux or Debian. You can also use a custom image created by your organization. To make the image compatible with Lambda, you must include the aws-lambda-go/lambda package in the image.

  • Using the Amazon base image for Go 1.x (legacy)

    Lambda will continue to support the Go 1.x base image until maintenance support for the Amazon Linux AMI ends on December 31, 2023. We recommend that you use the provided.al2 custom runtime instead of the Go 1.x base image.

Tip

To reduce the time it takes for Lambda container functions to become active, see Use multi-stage builds in the Docker documentation. To build efficient container images, follow the Best practices for writing Dockerfiles.

This page explains how to build, test, and deploy container images for Lambda.

Amazon base images for Go

Amazon provides the following base image for Go:

Tags Runtime Operating system Dockerfile Deprecation

1

Go 1.x Amazon Linux Dockerfile for Go 1.x on GitHub

Dec 31, 2023

Amazon Elastic Container Registry repository: gallery.ecr.aws/lambda/go

Go runtime interface client

The aws-lambda-go/lambda package includes an implementation of the runtime interface. For examples of how to use aws-lambda-go/lambda in your image, see Using the provided.al2 Amazon base image or Using a non-Amazon base image.

Using the provided.al2 Amazon base image

Go is implemented differently than other managed runtimes. Because Go compiles to native code, Lambda treats Go as a custom runtime. We recommend that you use the provided.al2 base image for custom runtimes to build container images for Go functions.

Tags Runtime Operating system Dockerfile Deprecation

al2

Custom Runtime Amazon Linux 2 Dockerfile for Custom Runtime on GitHub

alami

Custom Runtime Amazon Linux Dockerfile for Custom Runtime on GitHub

Dec 31, 2023

For more information about these base images, see provided in the Amazon ECR public gallery.

You must include the aws-lambda-go/lambda package with your Go handler. This package implements the programming model for Go, including the runtime interface.

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

To build and deploy a Go function with the provided.al2 base image.
  1. Create a directory for the project, and then switch to that directory.

    mkdir hello cd hello
  2. Initialize a new Go module.

    go mod init example.com/hello-world
  3. Add the lambda library as a dependency of your new module.

    go get github.com/aws/aws-lambda-go/lambda
  4. Create a file named main.go and then open it in a text editor. This is the code for the Lambda function. You can use the following sample code for testing, or replace it with your own.

    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. Use a text editor to create a Dockerfile in your project directory. The following example Dockerfile uses a multi-stage build. This allows you to use a different base image in each step. You can use one image, such as a Go base image, to compile your code and build the executable binary. You can then use a different image, such as provided.al2, in the final FROM statement to define the image that you deploy to Lambda. The build process is separated from the final deployment image, so the final image only contains the files needed to run the application.

    You can use the optional lambda.norpc tag to exclude the Remote Procedure Call (RPC) component of the lambda library. The RPC component is only required when using the Go 1.x runtime. Excluding the RPC reduces the size of the deployment package.

    Example — Multi-stage build Dockerfile
    Note

    Make sure that the version of Go that you specify in your Dockerfile (for example, golang:1.20) is the same version of Go that you used to create your application.

    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:al2 COPY --from=build /helloworld/main ./main ENTRYPOINT [ "./main" ]
  6. 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 --platform linux/amd64 -t docker-image:test .
    Note

    The command specifies the --platform linux/amd64 option to ensure that your container is compatible with the Lambda execution environment regardless of the architecture of your build machine. If you intend to create a Lambda function using the ARM64 instruction set architecture, be sure to change the command to use the --platform linux/arm64 option instead.

Use the runtime interface emulator to locally test your image. The runtime interface emulator is included in the provided.al2 base image.

To run the runtime interface emulator on your local machine
  1. Start the Docker image with the docker run command. Note the following:

    • docker-image is the image name and test is the tag.

    • ./main is the ENTRYPOINT from your Dockerfile.

    docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \ --entrypoint /aws-lambda/aws-lambda-rie \ docker-image:test \ ./main

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

  2. From a new terminal window, post an event to the following endpoint using a curl command:

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

    This command invokes the function with an empty event and returns a response. Some functions might require a JSON payload. Example:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
  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 Amazon Web Services Region where you want to create the Amazon ECR repository.

    • Replace 111122223333 with your Amazon Web Services account ID.

    aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn
  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:cn-north-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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 <ECRrepositoryUri> with the repositoryUri that you copied. Make sure to include :latest at the end of the URI.

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

    Example:

    docker tag docker-image:test 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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 build the image again, upload the new image to the Amazon ECR repository, and then use the update-function-code command to deploy the image to the Lambda function.

Using a non-Amazon base image

You can build a container image for Go from a non-Amazon base image. The example Dockerfile in the following steps uses an Alpine base image.

You must include the aws-lambda-go/lambda package with your Go handler. This package implements the programming model for Go, including the runtime interface.

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

To build and deploy a Go function with an Alpine base image
  1. Create a directory for the project, and then switch to that directory.

    mkdir hello cd hello
  2. Initialize a new Go module.

    go mod init example.com/hello-world
  3. Add the lambda library as a dependency of your new module.

    go get github.com/aws/aws-lambda-go/lambda
  4. Create a file named main.go and then open it in a text editor. This is the code for the Lambda function. You can use the following sample code for testing, or replace it with your own.

    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. Use a text editor to create a Dockerfile in your project directory. The following example Dockerfile uses an Alpine base image.

    Example Dockerfile
    Note

    Make sure that the version of Go that you specify in your Dockerfile (for example, golang:1.20) is the same version of Go that you used to create your application.

    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. 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 --platform linux/amd64 -t docker-image:test .
    Note

    The command specifies the --platform linux/amd64 option to ensure that your container is compatible with the Lambda execution environment regardless of the architecture of your build machine. If you intend to create a Lambda function using the ARM64 instruction set architecture, be sure to change the command to use the --platform linux/arm64 option instead.

Use the runtime interface emulator to locally test the image. You can build the emulator into your image or install it on your local machine.

To install and run the runtime interface emulator on your local machine
  1. From your project directory, run the following command to download the runtime interface emulator (x86-64 architecture) from GitHub and install it on your local machine.

    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

    To install the arm64 emulator, replace the GitHub repository URL in the previous command with the following:

    https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
  2. Start the Docker image with the docker run command. Note the following:

    • docker-image is the image name and test is the tag.

    • /main is the ENTRYPOINT from your Dockerfile.

    docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \ --entrypoint /aws-lambda/aws-lambda-rie \ docker-image:test \ /main

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

  3. Post an event to the following endpoint using a curl command:

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

    This command invokes the function with an empty event and returns a response. Some functions might require a JSON payload. Example:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
  4. Get the container ID.

    docker ps
  5. 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 Amazon Web Services Region where you want to create the Amazon ECR repository.

    • Replace 111122223333 with your Amazon Web Services account ID.

    aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn
  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:cn-north-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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 <ECRrepositoryUri> with the repositoryUri that you copied. Make sure to include :latest at the end of the URI.

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

    Example:

    docker tag docker-image:test 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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 build the image again, upload the new image to the Amazon ECR repository, and then use the update-function-code command to deploy the image to the Lambda function.

Using the Amazon base image for Go 1.x (legacy)

We recommend that you use the provided.al2 custom runtime instead of the Go 1.x base image. Lambda will continue to support the Go 1.x base image until maintenance support for the Amazon Linux AMI ends on December 31, 2023. For more information about Amazon Linux AMI support, see Amazon Linux AMI FAQs.

If you're using the Go 1.x base image, you must migrate your functions to provided.al2. No code changes are required for this migration. The only required changes relate to how you build your deployment package and which runtime you use to create your function. For more information, see Using the provided.al2 Amazon base image.

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

  1. Create a directory for the project, and then switch to that directory.

    mkdir hello cd hello
  2. Initialize a new Go module.

    go mod init example.com/hello-world
  3. Add the lambda library as a dependency of your new module.

    go get github.com/aws/aws-lambda-go/lambda
  4. Create a file named main.go and then open it in a text editor. This is the code for the Lambda function. You can use the following sample code for testing, or replace it with your own.

    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. Build the Go project. This command creates an executable called main.

    GOOS=linux GOARCH=amd64 go build -o main main.go

    Setting GOOS to linux and GOARCH to amd64 ensures that the compiled executable is compatible with the architecture of the Go base image, even if you compile it in a non-Linux environment.

  6. Create a new Dockerfile. The example Dockerfile uses the following configuration:

    • FROM: The URI of the base image that you want to use.

    • COPY: Copies the function code into the /var/task directory in your image.

    • CMD: The Lambda function handler or executable.

    FROM public.ecr.aws/lambda/go:1 # Copy function handler executable COPY main ${LAMBDA_TASK_ROOT} # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "main" ]
  7. 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 --platform linux/amd64 -t docker-image:test .
    Note

    The command specifies the --platform linux/amd64 option to ensure that your container is compatible with the Lambda execution environment regardless of the architecture of your build machine. If you intend to create a Lambda function using the ARM64 instruction set architecture, be sure to change the command to use the --platform linux/arm64 option instead.

  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. From a new terminal window, post an event to the following endpoint using a curl command:

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

    This command invokes the function with an empty event and returns a response. If you're using your own function code rather than the sample function code, you might want to invoke the function with a JSON payload. Example:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
  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 Amazon Web Services Region where you want to create the Amazon ECR repository.

    • Replace 111122223333 with your Amazon Web Services account ID.

    aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn
  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:cn-north-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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 <ECRrepositoryUri> with the repositoryUri that you copied. Make sure to include :latest at the end of the URI.

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

    Example:

    docker tag docker-image:test 111122223333.dkr.ecr.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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.cn-north-1.amazonaws.com.cn/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 build the image again, upload the new image to the Amazon ECR repository, and then use the update-function-code command to deploy the image to the Lambda function.