I'm trying to build and deploy multiple Go based lambdas using 1 Dockerfile (as the instructions don't differ between lambdas) using different go packages for each lambda.
My file structure is as follows:
test-lambda
|------ go.mod
|------ go.sum
|------ main.go
test-lambda-2
|------ go.mod
|------ go.sum
|------ main.go
Dockerfile
...other repo files
My Dockerfile looks like the following:
FROM golang:1.24.3 AS builder
ARG LAMBDA_DIR
RUN echo $LAMBDA_DIR
WORKDIR ${LAMBDA_DIR}
COPY * /lambda/
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -C /lambda -a -installsuffix cgo -o lambda
RUN chmod +x /lambda/lambda
FROM public.ecr.aws/lambda/provided:al2023-arm64
COPY --from=builder lambda/lambda /usr/local/bin/lambda
ENTRYPOINT [ "lambda" ]
I am using AWS CloudFormation and SAM to build and deploy the lambdas. My template.yaml
looks like this
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Architectures: [arm64]
Timeout: 900
MemorySize: 1024
Parameters:
CommitHash:
Type: String
Description: Commit hash of the change
Resources:
TestLambda:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Metadata:
Dockerfile: Dockerfile
DockerContext: .
DockerTag: !Ref CommitHash
DockerBuildArgs:
LAMBDA_DIR: /test-lambda
TestLambda2:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Metadata:
Dockerfile: Dockerfile
DockerContext: .
DockerTag: !Ref CommitHash
DockerBuildArgs:
LAMBDA_DIR: /test-lambda-2
I am then using a justfile
to make running the commands easier in CI (GitLab). The commands are as follows:
build:
sam build \
--use-container \
-t template.yaml \
--parameter-overrides CommitHash=$CI_COMMIT_SHORT_SHA \
--debug
deploy:
sam deploy \
--stack-name $CI_PROJECT_NAME--$CI_COMMIT_BRANCH \
--region eu-west-2 \
--profile $CI_PROJECT_NAME \
--resolve-s3 \
--resolve-image-repos \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
--parameter-overrides CommitHash=$CI_COMMIT_SHORT_SHA \
--tags Service=$CI_PROJECT_NAME Repo=$CI_PROJECT_URL Version=$CI_COMMIT_SHORT_SHA
My main.go
's look like this:
// main.go
package main
import (
"github.com/aws/aws-lambda-go/lambda"
)
func hello() (string, error) {
return "Hello λ!", nil
}
func main() {
// Make the handler available for Remote Procedure Call by AWS Lambda
lambda.Start(hello)
}
The only difference between the 2 is the returned string differs between each lambda package so that I can test they're different. The test-lambda-2
returns return "Hello λ2!", nil
for example.
This builds fine, but the issue I am having is that both lambdas are seemingly using the same image, and returning the output of the test-lambda-2
package, and not the respective packages.
I can provide the CI output if necessary, but from the logs I can see 2 different images being built and 2 repos with 2 separate images in. Both lambdas point to the each repo. So it seems to be an issue with the build and not the pushing of the image.
Am I missing something obvious?
Tried adjusting the building to use container or not, and adjusted the build arg. Both result in the same thing
There are few issues with the setup, You have to fix those before trying again,
In your Dockerfile, the COPY instruction is incorrect. You're trying to copy files to
/lambda/
but your WORKDIR is set to
${LAMBDA_DIR}
Also, you need to copy the specific lambda directory contents.
Here's the corrected Dockerfile:
FROM golang:1.24.3 AS builder
ARG LAMBDA_DIR
WORKDIR /lambda
COPY ${LAMBDA_DIR} .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -a -installsuffix cgo -o lambda
RUN chmod +x lambda
FROM public.ecr.aws/lambda/provided:al2023-arm64
COPY --from=builder /lambda/lambda /usr/local/bin/lambda
ENTRYPOINT [ "lambda" ]
In your Dockerfile, the COPY instruction is incorrect.
In your SAM template, you should specify the function handler and other required properties[1]
Make sure each lambda directory has the required AWS Lambda dependencies in its go.mod: [2]
require github.com/aws/aws-lambda-go v1.41.0
Each main.go should implement the Lambda handler interface
package main
import (
"context"
"github.com/aws/aws-lambda-go/lambda"
)
func handleRequest(ctx context.Context, event interface{}) (string, error) {
// Your lambda logic here
return "Hello from Lambda!", nil
}
func main() {
lambda.Start(handleRequest)
}
go
To build and deploy using SAM:
# Build
sam build
# Deploy
sam deploy --stack-name your-stack-name --parameter-overrides CommitHash=your-commit-hash
Sources
[1] SAM to deploy Image-Based Lambda
[2] Deploy Lambda functions with container images - AWS Prescriptive Guidance