Go functions on AWS Lambda in Docker
Uses the following technologies:
- Go programming language
- Docker as container
- AWS Lambda to host the function
- AWS ECR (Elastic Container Registry) to host the Docker image
- AWS API Gateway to expose the Lambda function as a REST API
- AWS CLI tool (
aws
) to configure AWS
The current setup in this project is: 1 REST endpoint → 1 Lambda function → inside 1 Docker image.
Based on Docker Hub: aws-lambda-go and this example Gist. See also:
- AWS:
- Docker:
- Other:
Write your Lambda function in Go
Edit my-lambda-function/main.go
Building both Go binary and Docker image
make
(Optional: Manual build steps for Go binary and Docker image)
Build Go binary
Create the working directory
mkdir my-lambda-function
Change to the directory
cd my-lambda-function
(Create the files: main.go
and Dockerfile
)
Initialize the module in Go
go mod init example.com/my-lambda-function
Build the go app for Linux
GOOS=linux go build
Build Docker image
To build your Docker image:
docker build -t my-lambda-function .
Running the Lambda function locally
To run your image locally:
docker run -p 9000:8080 my-lambda-function
In a separate terminal, you can then locally invoke the function using cURL:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"name":"Tom"}'
{"message":"Hello! Dear Tom!"}
Deploy to AWS Lambda
Parameters used below:
[my-lambda-function]
: substitute with your app/repository/image name[AWS Account Number]
: e.g.123456789012
[Region]
: e.g.eu-west-1
,us-east-1
Create an IAM Policy (e.g. ECRDockerImageCreation
) with the following permissions:
ecr:*
You also need an IAM Role (e.g. lambda-ex
) for executing the Lambda function.
Build your local Docker image:
make
Create a new Lambda function
Authenticate the Docker CLI to your Amazon ECR registry:
aws ecr get-login-password --region [Region] | docker login --username AWS --password-stdin [AWS Account Number].dkr.ecr.[Region].amazonaws.com
Login Succeeded
Tag your new Docker image to match your repository name:
docker tag [my-lambda-function]:latest [AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest
(You won’t get any response)
Create an ECR repository:
aws ecr create-repository --repository-name [my-lambda-function] --region [Region]
Deploy the Docker image to Amazon ECR:
docker push [AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest
You should now see your image repository on https://console.aws.amazon.com/ecr/repositories?region=[Region]
aws lambda create-function --region [Region] --function-name [my-lambda-function] \
--package-type Image \
--code ImageUri=[AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest \
--role arn:aws:iam::[AWS Account Number]:role/lambda-ex
Turn the Lambda function into a REST API using AWS API Gateway
- Go to https://console.aws.amazon.com/apigateway
- REST API → Build
- Select
🔘 “New API” - Actions → Create Resource, enter resource name e.g.
my-lambda-function
- Select your created resource, then Actions → Create Method
- Select method (e.g.
POST
, orANY
) - Select Integration type:
🔘 “Lambda Function”, then check the☑️ “Use Lambda Proxy integration” and enter the name of your function under “Lambda Function” - Actions → Deploy API
- Enter a “Stage” name e.g. “test”
You will get an endpoint back, e.g. https://12345xw4tf.execute-api.eu-west-1.amazonaws.com/test
(note: excludes the function name, see the full curl
example below)
curl -XPOST "https://12345xw4tf.execute-api.eu-west-1.amazonaws.com/test/my-lambda-function" -d '{"name":"Tom"}'
Update an existing Lambda function
Tag your new Docker image to match your repository name:
docker tag [my-lambda-function]:latest [AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest
Deploy the Docker image to Amazon ECR:
docker push [AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest
Update the Lambda function:
aws lambda update-function-code --region [Region] --function-name [my-lambda-function] \
--image-uri=[AWS Account Number].dkr.ecr.[Region].amazonaws.com/[my-lambda-function]:latest
Note: There’s no need to update API Gateway after updating the Lambda function.
Troubleshooting
- Note that your Lambda function and API Gateway will have separate Log Groups in CloudWatch.
- If you get API Gateway "Internal server error", "malformed Lambda proxy response" errors or 502 status codes, it means your Lambda function’s response is not formatted correctly for API Gateway.