- [Russ] We have another place where you can run your code from a container image: AWS Lambda. If you aren't already familiar, Lambda is a serverless compute service, where you can run your code without provisioning or managing servers. With Lambda, you pay for what you use. I write some code, hand it on to Lambda, where it is run for me. The code can be run when I ask Lambda to run it, or it can run in a response to an event in AWS, like an object getting added to an S3 bucket. Lambda has built-in support for Node, Python, Java, .Net, Go, and Ruby programming languages. The package size of your function is currently limited to 50 MB. But what if I have some code that isn't a supported language? What if I had some larger dependencies that I wanted to include with my code? We can solve this by supplying Lambda a container image that contains all the code and dependencies we want to run. Running a container image in Lambda comes with all the benefits of running your code on Lambda: operational simplicity, automatic scaling, high availability, and integrations with many AWS services. Again, you're only paying for what you use on Lambda. Your Lambda payload is a container image, so you can use tools you are familiar with, like Docker, to build and maintain images. We've decided our project, we want to run on Lambda. The container image supplied to Lambda will need to implement the Lambda runtime API. This is how your container will retrieve invocations and parameters from the Lambda service, and respond back with results. Let's walk through the sequence this happens in. First, Lambda is asked to invoke a function. A function invocation includes an event payload supplied to your code. Think of this as a parameter to your function. Inside your container, you are polling the next method to find any invocations. This is the container code asking Lambda: do you have any invocations for me? The response from the next method includes the event payload. Your code in the container processes the event, and sends the response to Lambda with the runtime API response method. You probably want to test this cycle locally in your own environment, before deploying anything to Lambda, and you can! The AWS Lambda Runtime Interface Emulator or RIE, can simulate the communication from the Lambda service, so you can test locally. AWS has supplied base container images with an implementation of the runtime API for Python, Node.js, Java, .Net, Go, and Ruby. These base images also contain the RIE. So, if you are working these languages, there's already a base container you can start from. I have an example in my AWS Cloud9 instance, where we can see all this working. I have an old Bash script I use to check if my SSL certificates are about to expire. Sounds like the kind of thing I would like to run in Lambda, but Bash isn't an out-of-the-box supported language. I'll need to create a container image that implements the runtime interface and runs my Bash script. My Docker file starts with a FROM public.ecr.aws/lambda/provided:al2 container. I'm starting with an AWS supplied container image, that has the RIE already installed, and sets up some environment variables for me. I use the YUM package manager, here, to install some dependencies. My script has OpenSSL, and updates some certificate authorities. The container expects a bootstrap script in the runtime directory. The script has my implementation of the runtime API. And then I copy in my ssl_tester script, here. The final CMD is where the handler code lives. This will be made available to my bootstrap script, as an environment variable, _HANDLER. Let's take a look at the bootstrap script. Here we see the two runtime methods, next and response. We grab the event data by using cURL to access the next API, here. This will block here, if there are no invocations to run. The requests from this response include a request ID, so we grab that and store it. Then we run the _HANDLER, here, and pass along the event payload data. In this case, the handler is the ssl_tester script. I store the response from a script, and finally, I can use cURL again, here, to POST the response to the runtime API response method. The full URL to the method includes the request ID we stored earlier. The ssl_tester script is pretty simple. The script expects a JSON array of domain names. We looped through the domain names, and use OpenSSL to make a connection and check the expiry date. All of the results are combined into a JSON array, and returned. This is the response to bootstrap script we'll send back to Lambda. I can build the container here, in my local environment with docker build. And I can run the container with docker run. Why did I expose a port on that container? Because the Runtime Interface Emulator is available in the AWS supplied container. I can test my Lambda function, here, before I deploy anything. I want to simulate an invocation with a JSON an array of domains. In a new terminal window, I use cURL to send the POST, and I get back a JSON array of certificate expiry dates. So that's doing exactly what I want it to do. So I'm ready to run the container image in Lambda. I need to tag the container and push it up to ECR. I use docker tag and docker push. Now my container is in ECR, we can go to Lambda. I want to create a function. I go to Create function. I'm using a container image. Let's call the function, ssl-tester. The container image has pushed. I can just select that. I select the image, and I can Create function. The function is created, and now I want to test it. I jump over to the Test tab. I create a new test event. I'll use the same array of domain names I used when I was testing locally. I can Save, I need to give it a name, Save, and Test. The function ran successfully, and if I expand this section, I see my JSON response that contains the domain names and expiry dates for each certificate. Very cool. Exactly the same container image I was running locally, is now being run by AWS infrastructure. I'm getting all the benefits of running my code in Lambda, and I'm able to build exactly the container image I want using Docker tools I'm familiar with.