Have installed
With CDK Docker bundling you can deploy GO Lambda functions without having go locally installed. Usually it’s more efficient to build GO with the GO compiler. But in the case you dont want to install the GO tools, you can build the GO app inside a local Docker container.
We distinguish three different types of Container usage with lambda:
With sam local start-lambda
you can run Lambda functions in local Containers. See SAM Developer Guide for usage.
Here you can find images to run Lambda functions
See the lambci project.
You find the images in the docker hub: lambdci lambda image
See Chapter Lambda Container Deployment
In Chapter Create a GO Lambda Function you see how to build a GO App.
If you don`t want to install GO locally, maybe you have top have a clean separation from development and deployment, you may use the CDK Docker bundling feature.
You may use any container with GO included, or just use the prebuild AWS SAM images. The AWS SAM project pushed images to the AWS public ECR registry
In this example public.ecr.aws/sam/build-go1.x:latest is used.
25 handler := lambda.NewFunction(this, aws.String("GoLangDockerECRImageBundle"),
26 &lambda.FunctionProps{
27 Handler: aws.String("main"),
28 Runtime: lambda.Runtime_GO_1_X(),
29 Code: lambda.AssetCode_FromAsset(aws.String("../app"), &asset.AssetOptions{
30 Bundling: &cdk.BundlingOptions{
31 Image: lambda.Runtime_GO_1_X().BundlingImage(),
32 User: aws.String("root"),
33 Command: &[]*string{
34 aws.String("bash"),
35 aws.String("-c"),
36 aws.String("go version && go build -o /asset-output/main"),
37 },
38 },
39 }),
40 },
41 )
You see in line 31 the used Docker image.
The app is build with normal go build
command.
The type of the deployment demands that you write the output file in the /asset-output directory. (Line 36). Please note, that you have to use a ZIP package when the Lambda function needs additional files.
The “go version” command is just to mirror the example from the CDK Book. It’s not needed for the build.
Although it is not recommended from security perspective, this only works with user root (Line 32).
The first time you execute
go test
In the infrastructure-as-go/cdk-go/lambda/deploy_bundler/infra
directory you will see the output:
Bundling asset MyStack/GoLangDockerECRImageBundle/Code/Stage...
Unable to find image 'public.ecr.aws/sam/build-go1.x:latest' locally
latest: Pulling from sam/build-go1.x
...
That show you that the Docker images are pulled from the public.ecr.aws
.
Suppose you change just one line of code in the Lambda app in infrastructure-as-go/cdk-go/lambda/deploy_bundler/app/main.go
, the Deployment now has two phases, which takes some time (more than one minute):
cdk deploy
Bundling asset DockerbundlerStack/GoLangDockerECRImageBundle/Code/Stage...
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
go version go1.17.5 linux/amd64
go: downloading github.com/aws/aws-lambda-go v1.27.0
✨ Synthesis time: 9.68s
DockerbundlerStack: deploying...
[0%] start: Publishing 00ff15471bdba4032c0379cb904af48c1eae15ba923e7e3d012615656ce533c5:current_account-current_region
[50%] success: Published 00ff15471bdba4032c0379cb904af48c1eae15ba923e7e3d012615656ce533c5:current_account-current_region
[50%] start: Publishing 6bdc278bdbefc18398c6b43671e3364bcdb803f16fbaef4e4901cf4242c7efa7:current_account-current_region
[100%] success: Published 6bdc278bdbefc18398c6b43671e3364bcdb803f16fbaef4e4901cf4242c7efa7:current_account-current_region
DockerbundlerStack: creating CloudFormation changeset...
...
✅ DockerbundlerStack
✨ Deployment time: 61.55s
Outputs:
DockerbundlerStack.lambdabundle = DockerbundlerStack-GoLangDockerECRImageBundle68C01-UevXVHkSLeks
Stack ARN:
arn:aws:cloudformation:eu-central-1:795048271754:stack/DockerbundlerStack/caa390a0-7142-11ec-8b1d-06a376f57136
✨ Total time: 71.23s
If you deploy changed code in the infrastructure-as-go/cdk-go/lambda/deploy_bundler/app
directory with:
time task fastdeploy
the deployment process takes less then 4 seconds.
time task fastdeploy
task: [build] env GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w" -o ../dist/main main.go
task: [build] chmod +x ../dist/main
task: [build] cd ../dist && zip main.zip main
adding: main (deflated 60%)
task: [fastdeploy] aws lambda update-function-code --function-name DockerbundlerStack-GoLangDockerECRImageBundle68C01-UevXVHkSLeks --zip-file fileb://../dist/main.zip
{
"FunctionName": "DockerbundlerStack-GoLangDockerECRImageBundle68C01-UevXVHkSLeks",
"FunctionArn": "arn:aws:lambda:eu-central-1:795048271754:function:DockerbundlerStack-GoLangDockerECRImageBundle68C01-UevXVHkSLeks",
"Runtime": "go1.x",
...
}
task fastdeploy 1,34s user 0,57s system 52% cpu 3,601 total
So its 20 times faster than the bundling deployment.
On a developer workstation GO should be installed, so you dont need the bundling option.
In a CI/CD pipeline its no problem to install GO, see Chapter Architecture - Serverless DynamoDB, S3, Lambda with the CodeBuild buildspec.yml as an example.
So this deployment type is only useful if you want to deploy from non-developer workstations, for example if you usually develop in another language, dont want to deal with GO, but you have no CI/CD pipeline.