Speeding up sample Sam Build

 


The Sample

If you are new on Lambda, you probably started using SAM samples which offers a nice way to avoid building from scratch. We supposed to have the usual "HelloWorldFunction" triggered by ApiGateway.


If you are using the Lambda function built from Docker Image, you have a Docker file which is created to be "general purpose" and uses the power of container without touching your local environment.


Let's look at this file

---------------------------------------------------------------------------------------------------------------

FROM public.ecr.aws/sam/build-java11:latest as build-image


WORKDIR "/task"

COPY src/ src/

COPY pom.xml ./


RUN mvn -q clean install

RUN mvn dependency:copy-dependencies -DincludeScope=compile


FROM public.ecr.aws/lambda/java:11


COPY --from=build-image /task/target/classes /var/task/

COPY --from=build-image /task/target/dependency /var/task/lib

# Command can be overwritten by providing a different command in the template directly.

CMD ["helloworld.App::handleRequest"]

------------------------------------------------------------------------------------------------------------

As you can see a container is created from public.ecr.aws/lambda/java:11 and in that container (you can see it running in your Docker) it copies the source file and starts the maven build.

There are 2 maven command:

  • The first line perform a local install in the local repository
  • The second line perform a copy of all the dependencies that the Lambda needs at runtime


The second one is of course mandatory if you want to run your Lambda function using external libraries: for example if you want to return a json and you want to use Jackson, you need to add it on pom.xml and let this command do the magic for you.


After maven operations, the docker command build the layer copying the dependencies from target and of course the class file. Now you have all the layers you need to run.

Speed UP

The problem is that: the folder in which the maven is performed is an ephimeral one, which means that it is created always empty, without history, so every time you launch the command, maven will download all the files it needs.

And this is a very waste of time.

To avoid this, you need to modify the Docker file by removing the maven command and leaving only the copy operation.


This of course means you need to perform the maven command before running the Sam build: you will setup maybe a bat file which performs:

mvn -q clean install -f HelloWorldFunction\pom.xml (just show errors)

mvn dependency:copy-dependencies -DincludeScope=compile -f HelloWorldFunction\pom.xml (package all dependencies)

I added the -f option because of the structure of the folder: the HelloWorldFunction contains Docker, maven and sources, while the external contains the template used by SAM


As you can see by yourself the SAM build will be very rapid (because the layer of dependencies is already cached and present). And if you perform just code changes (not in your pom.xml) you will see that only one layer will change (the one which contains the class files)


Conclusion

This is of course intended for studying how Lambda and how AWS infrastructure works, it's not intended for production environment.

But if you have a jenkins machine, you can configure it to react at a tag commit to:
  • make the build
  • perform the sam build
  • perform the sam deploy

and you can have such a pipeline for your lambda (or something similar)

Commenti

Post popolari in questo blog

HTML and AI - A simple request, and a beautiful response for ElasticSearch without Kibana

A simple CD using AWS Pipeline

Websocket Chat with Lambda (but all in Java)