Lambda functions are typically executed in environments created from the default runtimes provided by AWS (such as python3.13 or ruby3.4).
These runtimes come pre-loaded with many popular modules, like boto3 (the Python AWS SDK), so you often don’t need to install additional dependencies for routine tasks.
However, you may eventually need a module that isn’t included in the default runtimes. You have several options to solve this:
- Create Lambda layers with the dependencies you need, and associate the layer with your function
- Create Lambda functions from Docker containers
Both options will solve your problem, but they’re overkill if you only need a couple of modules. If you’re already managing your projects using an Infrastructure as Code (IaC) solution like CDK, you can use the bundling
option instead.
Example Scenario
Imagine you’re deploying a Lambda function defined in a file called cool_stuff.py
, located in a folder called lambdas
at the base level of your project. In your stack definition, you have the following code:
const awesomeLambda = new lambda.Function(this, 'awesomeLambda', {
runtime: lambda.Runtime.PYTHON_3_13,
code: lambda.Code.fromAsset('lambdas'),
handler: 'cool_stuff.handler',
timeout: cdk.Duration.seconds(30),
})
This creates a Lambda function using the specified asset (your file at lambdas/cool_stuff.py
), uses Python 3.13 as the runtime, and sets the timeout to 30 seconds. Suppose the file contains code like this:
import pymysql
...
def handler(event, context):
...
Running this Lambda will fail because none of the default runtimes include the pymysql
module. Fortunately, there’s an easy fix.
The Solution
First, create a requirements.txt
file next to your function:
Then, add the dependencies to the requirements.txt
file. In our case, it’s a single line:
pymysql==1.1.1
Now you can update your stack to use requirements.txt
. Pass additional arguments to the fromAsset
function with bundling instructions to ensure your Lambda includes the required dependencies:
const awesomeLambda = new lambda.Function(this, "awesomeLambda", {
runtime: lambda.Runtime.PYTHON_3_13,
code: lambda.Code.fromAsset("lambdas", {
bundling: {
image: lambda.Runtime.PYTHON_3_13.bundlingImage,
command: [
"bash",
"-c",
"pip install --no-cache -r requirements.txt -t /asset-output && cp -au . /asset-output",
],
},
}),
handler: "cool_stuff.handler",
timeout: cdk.Duration.seconds(30),
});
This builds your asset by executing a command in a Docker container and uses that as the base for the function runtime. When you deploy this version of the Lambda function, it will show the dependencies next to your function in the explorer panel:
This approach allows you to add Python dependencies to your Lambdas easily without leaving your CDK project and without using layers or other features.
Do I Need requirements.txt?
No, it’s not strictly necessary to have a requirements.txt
file. You can install dependencies directly in the command
section of the bundling definition:
const awesomeLambda = new lambda.Function(this, "awesomeLambda", {
runtime: lambda.Runtime.PYTHON_3_13,
code: lambda.Code.fromAsset("lambdas", {
bundling: {
image: lambda.Runtime.PYTHON_3_13.bundlingImage,
command: [
"bash",
"-c",
"pip install --no-cache pymysql -t /asset-output && cp -au . /asset-output",
],
},
}),
handler: "cool_stuff.handler",
timeout: cdk.Duration.seconds(30),
});
However, I still recommend using a requirements file because you’ll often need to install more than one module at a time, and having a dedicated requirements file tends to be the cleanest solution!
I hope you find this useful!