Last updated on August 29th, 2024 at 11:30 am
In this tutorial we are going to see Step by step AWS Lambda Docker deployment and how easily you can test your lambda functions by building a docker image. All this can be done by running the container on your local Computer / Desktop / MAC / Linux or Windows server.
I am going to execute the sample AWS Lambda function I have on my MAC. One of the awesome feature introduced by AWS as this option will provide us ability in migrating Lambda functions easily to container images.
Steps will be more or less the same in Windows Desktop. This is a simple beginners guide on configuring AWS lambda function within a Docker container.
Lets split this in to clear steps for the ease of understanding
- Step 1 : Install and Start Docker
- Step 2: Create python file named app.py with code
- Step 3: Create requirements.txt file and add each dependency package line by line
- Step 4: Create Dockerfile
- Step 5: Build the docker image and run the container
- Step 6: Use CURL to trigger the function
Note: I am using Python 3.9 as an example for this tutorial
For other programming languages refer AWS guide.
Step 1 : Install and Start Docker
You need to first install docker. If you don’t have docker already installed on your local system then follow the details below,
For MAC users, please use this step to install docker
For Windows users, follow this link
Assuming that you have docker installed and started let us go to the next step.
Step 2: Create python file named app.py with code
For the ease of managing the files and contents, let us create a folder / directory named my-lambda. Switch to this directory and proceed with creating a file named app.py and add your code. This can be the same code that you have on your original lambda function. All the files are created inside this my-lambda directory.
This is a demo and I am using very basic function with a package import
from simple_salesforce import Salesforce,SalesforceLogin
def lambda_handler(event, context):
return {
"statusCode": 200,
"headers": {'Content-Type': 'text/html'},
"body": "<html><body><title>Test Site</title><b>This is a test</b></body></html>"
}
As you can see I have a dependency for my code and it uses a package named simple_salesforce
Step 3: Create requirements.txt file and add each dependency package line by line
Let us create a requirements.txt file and add the package name that your code depends on, in my case it is simple_salesforce
$cat requirements.txt
simple_salesforce
Step 4: Create Dockerfile
We are all set now to create a dockerfile. Content of the file is shown below.
FROM public.ecr.aws/lambda/python:3.9
# Install the function's dependencies using file requirements.txt
# from your project folder.
COPY requirements.txt .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
# Copy function code
COPY app.py ${LAMBDA_TASK_ROOT}
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "app.lambda_handler" ]
Since I am using Python3.9, in the header of the file above I am calling that specific image. Take a look at this documentation to understand more https://docs.aws.amazon.com/lambda/latest/dg/python-image.html
Step 5: Build the docker image and run the container
Lets build the docker image now. I am giving my image name as local-lambda
$ docker build -t local-lambda:latest .
[+] Building 29.6s (9/9) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for public.ecr.aws/lambda/python:3.9 1.6s
=> [1/4] FROM public.ecr.aws/lambda/python:3.9@sha256:6b647484e0a9e9c332e1fc620845d89974cbff3e9008609dbe4a4785 21.3s
=> => resolve public.ecr.aws/lambda/python:3.9@sha256:6b647484e0a9e9c332e1fc620845d89974cbff3e9008609dbe4a4785f 0.0s
=> => sha256:6b647484e0a9e9c332e1fc620845d89974cbff3e9008609dbe4a4785f8cfc054 772B / 772B 0.0s
=> => sha256:792fdc65bb1f531a3ccdc15c4587133e62f2b136799f3d83b890ceb0f7cb9afa 3.00kB / 3.00kB 0.0s
=> => sha256:d09805cbf8c0b1ea54f3d29cce364af507e274a7d649a898f40dff058f9f9523 1.58kB / 1.58kB 0.0s
=> => sha256:069d51b0476dda9214121ccaffa3f73f342eb29db5933390e41138c9b69268fc 104.79MB / 104.79MB 5.9s
=> => sha256:ee7094de4c489a60dfd7ea2c7bbd586a9c1e42f30bff94abf709807174c1200f 85.88kB / 85.88kB 0.6s
=> => sha256:200b63deca0b4a4920d0089ebd8fd2dcd36e2a61ad1819c02643c089384cba1a 417B / 417B 0.4s
=> => sha256:072730bdc14dcc7275f5c0d3308c68c0c4826f70118d9c2214b7010c4b4e4122 2.40MB / 2.40MB 1.9s
=> => sha256:97466eb1c2ad95bd12266c4f07fb8e0aac48a3f198ef3271dba262a1fdb09a74 60.48MB / 60.48MB 14.0s
=> => sha256:103930488ac486a8141ddf2ca5b8ceb4382f9f6c776d2cb5a692e378f152f320 12.07MB / 12.07MB 6.4s
=> => extracting sha256:069d51b0476dda9214121ccaffa3f73f342eb29db5933390e41138c9b69268fc 7.9s
=> => extracting sha256:ee7094de4c489a60dfd7ea2c7bbd586a9c1e42f30bff94abf709807174c1200f 0.1s
=> => extracting sha256:200b63deca0b4a4920d0089ebd8fd2dcd36e2a61ad1819c02643c089384cba1a 0.0s
=> => extracting sha256:072730bdc14dcc7275f5c0d3308c68c0c4826f70118d9c2214b7010c4b4e4122 0.1s
=> => extracting sha256:97466eb1c2ad95bd12266c4f07fb8e0aac48a3f198ef3271dba262a1fdb09a74 5.0s
=> => extracting sha256:103930488ac486a8141ddf2ca5b8ceb4382f9f6c776d2cb5a692e378f152f320 1.3s
=> [internal] load build context 0.0s
=> => transferring context: 465B 0.0s
=> [2/4] COPY requirements.txt . 0.2s
=> [3/4] RUN pip3 install -r requirements.txt --target "/var/task" 5.8s
=> [4/4] COPY app.py /var/task 0.0s
=> exporting to image 0.5s
=> => exporting layers 0.5s
=> => writing image sha256:3995f2de2ed7701afd4fb35dc4ff594367eefc4a85e763eec222f2095d5f7b31 0.0s
=> => naming to docker.io/library/local-lambda:latest
Run docker images command
Verify the list of images and make sure that the above image named local-lambda got successfully build
Lets run the container
$docker run -p 9001:8080 local-lambda
18 Apr 2023 21:17:40,191 [INFO] (rapid) exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)
Step 6: Use CURL to trigger the function
The last step is to invoke the function using CURL and check the logs in the run command, launch a new terminal while keeping the other terminal(that ran the docker run command) open . You should be able to see the logs live by doing so.
$ curl -XPOST "http://localhost:9001/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
{"statusCode": 200, "headers": {"Content-Type": "text/html"}, "body": "<html><body><title>Test Site</title><b>This is a test</b></body></html>"}
In parallel you should be able to see the logs in the terminal window which you ran the docker run command
$ docker run -p 9001:8080 website-lambda
18 Apr 2023 21:17:40,191 [INFO] (rapid) exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)
18 Apr 2023 21:21:29,619 [INFO] (rapid) extensionsDisabledByLayer(/opt/disable-extensions-jwigqn8j) -> stat /opt/disable-extensions-jwigqn8j: no such file or directory
18 Apr 2023 21:21:29,619 [WARNING] (rapid) Cannot list external agents error=open /opt/extensions: no such file or directory
START RequestId: d84871f9-318d-4c89-b4f2-dbdb92627384 Version: $LATEST
END RequestId: d84871f9-318d-4c89-b4f2-dbdb92627384
REPORT RequestId: d84871f9-318d-4c89-b4f2-dbdb92627384 Init Duration: 0.54 ms Duration: 215.68 ms Billed Duration: 216 ms Memory Size: 3008 MB Max Memory Used: 3008 MB
As I always say, tried my best here to make things simple. Please let me know if you have any questions.