I have a golang application which I want to dockerize and run on AWS Lambda. Here is my Dockerfile:
FROM golang:1.21 as build
WORKDIR /app
RUN apt-get update
RUN apt-get install -y libvips libvips-dev
COPY go.mod go.sum ./
COPY main.go .
RUN GOOS=linux GOARCH=amd64 go build -o main main.go
FROM alpine:3.19
COPY --from=build /app/main /main
ENTRYPOINT [ "/main" ]
I install libvips because I am using bimg library for image compression.
Here is my minified go app:
package main
import (
"context"
"log"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/h2non/bimg"
)
var (
s3Client *s3.Client
)
func init() {
cfg, err := config.LoadDefaultConfig(context.Background())
if err != nil {
log.Fatalf("failed to load AWS config: %v", err)
}
s3Client = s3.NewFromConfig(cfg)
}
func main() {
lambda.Start(Handler)
}
func Handler(ctx context.Context, event events.S3Event) error {
// compress and upload and do stuff
return nil
}
Not only I get the error exec /main: no such file or directory
when I try to test the lambda from aws dashboard, but it also gives me the same error when I try to run the image on my local machine with the following command:
docker run --rm -it s3-image-compressor-lambda:latest
I know the lambda won't work on my local machine but I believe it shouldn't say file not found but rather I would expect a runtime error.
UPDATE: I added some commands to Dockerfile to try to debug to see what's going on.
I added RUN ls -l /
right after COPY of the main file and here is the output:
#16 [stage-1 4/7] RUN ls -l /
#16 0.354 total 18668
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 bin
#16 0.354 drwxr-xr-x 5 root root 340 Apr 4 22:28 dev
#16 0.354 drwxr-xr-x 1 root root 4096 Apr 4 22:28 etc
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 home
#16 0.354 drwxr-xr-x 7 root root 4096 Jan 26 17:53 lib
#16 0.354 -rwxr-xr-x 1 root root 19055376 Apr 4 22:06 main
#16 0.354 drwxr-xr-x 5 root root 4096 Jan 26 17:53 media
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 mnt
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 opt
#16 0.354 dr-xr-xr-x 459 root root 0 Apr 4 22:28 proc
#16 0.354 drwx------ 2 root root 4096 Jan 26 17:53 root
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 run
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 sbin
#16 0.354 drwxr-xr-x 2 root root 4096 Jan 26 17:53 srv
#16 0.354 dr-xr-xr-x 13 root root 0 Apr 4 22:28 sys
#16 0.354 drwxrwxrwt 2 root root 4096 Jan 26 17:53 tmp
#16 0.354 drwxr-xr-x 7 root root 4096 Jan 26 17:53 usr
#16 0.354 drwxr-xr-x 12 root root 4096 Jan 26 17:53 var
#16 DONE 0.4s
So there is actually a main file in the root directory.
After that I added RUN /main
to see what is gonna happen, and here is the output:
> [stage-1 8/8] RUN /main:
0.258 /bin/sh: /main: not found
FROM golang:1.21 as build
WORKDIR /app
RUN apt-get update
RUN apt-get install -y libvips libvips-dev
COPY go.mod go.sum main.go .
RUN go mod download
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 go build \
-tags netgo \
-o main main.go
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y libvips
COPY --from=build /app /app
ENTRYPOINT ["/app/main"]