- See
index.ts
for example for GraphQL setup. - See
express.ts
for example for Express setup withGET /
- Using AWS SAM CLI
sam
is probably the easiest way to deploy lambda based applications.
samconfig.toml
: AWS SAM configuration file.cloudformation-resources-v3.yaml
: AWS SAM template file, essentially a CloudFormation template file. By default this should be namedtemplate.yaml
.- This is almost the same as
cloudformation-resources-v2.yaml
. But runningsam build
will automatically build the image based on theMetadata
field.
- This is almost the same as
-
Prepare the application for later deployment or local testing:
sam build -t cloudformation-resources-v3.yaml
sam build
create a.aws-sam
folder.- If template is called
template.yaml
,-t
option can be omitted.
-
Deploy the application:
sam deploy
- If
samconfig.toml
hasn't been created already, or we are running deploy for the first time, we can add--guided
. - No need to use
-t cloudformation-resources-v3.yaml
likesam build
, because this will actually use.aws-sam/build/template.yaml
created insam build
step.
- If
Delete the stack:
sam delete
- No need to use
-t cloudformation-resources-v3.yaml
, because needed information is stored
-
(One time setup) Provision ECR:
aws --region us-west-2 \ cloudformation deploy \ --template-file cloudformation-ecr.yaml \ --stack-name TestEcr
-
Read the output of the stack to get the ECR URI for future steps:
aws --region us-west-2 \ cloudformation describe-stacks \ --stack-name TestEcr \ | jq ".Stacks[0].Outputs"
Example output:
[ { "OutputKey": "RepositoryUriForLambda", "OutputValue": "<ecr_uri>" } ]
-
Build the image and tag with the ECR URI:
docker build -t <ecr_uri>:<version> .
(Optional) We can tag the image with ECR URI later:
docker tag <local_image_name> <ecr_uri>:<version>
-
(Optional) Test the function locally:
docker run -p 9000:8080 <ecr_uri>:<version>
In a separate terminal, run:
curl "http://localhost:9000/2015-03-31/functions/function/invocations" \ -d '{"payload":"hello world!"}'
-d '{"payload":"hello world!"}'
will only work forGET /
route in Express.
-
Login to ECR with Docker:
aws --region us-west-2 ecr get-login-password \ | docker login <ecr_uri> \ --username AWS \ --password-stdin
-
Push the image to ECR:
docker push <ecr_uri>:<version>
-
Deploy the CloudFormation stack:
aws --region us-west-2 cloudformation deploy \ --template-file cloudformation-resources.yaml \ --stack-name TestResources \ --capabilities CAPABILITY_NAMED_IAM \ --parameter-overrides \ LambdaFunctionImageUri="<ecr_uri>:<version>"
-
(Optional) Test the endpoint (GraphQL API):
curl 'https://<api_gateway_domain>/graphql' \ -H 'content-type: application/json' \ -d '{"query":"{ hello }"}'
-H 'content-type: application/json'
is required for GraphQL requests.
-
Delete the stacks (both
TestResources
andTestEcr
):aws --region us-west-2 cloudformation delete-stack \ --stack-name TestResources
-
Delete the ECR:
-
(Optional) List the images:
aws --region us-west-2 ecr list-images \ --repository-name <ecr_name>
-
Delete all images:
aws --region us-west-2 ecr batch-delete-image \ --repository-name <ecr_name> \ --image-ids imageTag=v1 imageTag=v2
-
Delete the repository:
aws --region us-west-2 cloudformation delete-stack \ --stack-name TestEcr
-
-
serverless-http is the library to convert a regular Express app into a lambda handler.
-
Docker image must use arm64 version, i.e.
public.ecr.aws/lambda/nodejs:18-arm64
, which matches theArchitectures
property of the lambda function. -
AWS::Serverless::Function
is used instead ofAWS::Lambda::Function
so we don't have to create IAM roles and policies for the lambda function ourselves. -
In
cloudformation-resources-v1.yaml
, theSourceArn
field ofAWS::Lambda::Permission
can be ignored. If you want to specify it, the resource-path must match theAWS::ApiGatewayV2::Route
's ARN. Otherwise, it will show as error in Lambda > Triggers section of AWS Console. For example:- If
AWS::ApiGatewayV2::Route
hasRouteKey
set toGET /
, then theSourceArn
should bearn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayApiHttp.ApiId}/*/*/
, where it ends with/*/*/
instead of/*/*/*
. BecauseAWS::ApiGatewayV2::Route
didn't define path/*
. - For
POST /graphql
, it should bearn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayApiHttp.ApiId}/*/*/graphql
.
See https://docs.aws.amazon.com/apigateway/latest/developerguide/arn-format-reference.html for ARN format for API Gateway. The stage and http-method part can still be "*".
- If
-
In
cloudformation-resources-v2.yaml
, we usedAWS::Serverless::Api
to simplify the creation of API Gateway.