I've got some apparently conflicting concerns when deploying Lambda functions using CDK:
The way I do this currently is clunky:
bundling_options = BundlingOptions(
image=aws_lambda.Runtime.PYTHON_3_8.bundling_docker_image,
command=["backend/bundle.bash", directory],
)
return aws_lambda.Code.from_asset(path=".", bundling=bundling_options)
poetry export
to convert the relevant entries from Poetry to pip requirements.txt format and installs using pip install --target=/asset-output
(because Poetry doesn't support installing into a specific directory), thendirectory
and its parent directory (the shared files) to /asset-output.I have to use path="."
above because the Docker container needs to read pyproject.toml and poetry.lock from the root of the project. This seems to be causing another issue, where any change to any file in the entire repository causes a redeployment of every Lambda function. This is the main reason I'm looking for alternatives.
Is there a better way to share files between Lambda functions in CDK, where the Lambda functions have different dependencies?
Some bad options:
PythonFunction
, because it assumes that the requirements.txt file is in the root directory (which is shared between Lambda functions).asset_hash
in from_asset
. Unfortunately, this adds considerable brittleness and complexity (hashing every possibly relevant file) rather than simplifying.Coming from the Node.js world (NodejsFunction
) where dependencies are simply excluded from the bundle if they're not used, I'm unsatisfied with my solution but here it is:
I have a pyproject.toml and poetry.lock file at the root of my repository where I define all of my dependencies for all lambdas. My virtual env uses these dependencies. Then I manually add requirements.txt files in my lambdas/
folder with only the dependencies I need for that lambda ensuring the version matches what I have in pyproject.toml. Then I use PythonFunction
throughout my CDK app. See screenshot below of folder setup.
Regarding needing common code shared between lambdas, I added a common/
folder adjacent to lambdas/
. Then, I'd mount the common code into the bundling docker container upon build. Example:
fn = lambda_py.PythonFunction(
self,
"TransformDataFn",
bundling=lambda_py.BundlingOptions(
volumes=DockerVolume(
container_path="/asset-input/common",
host_path=path.join(dir_path, "../../common"),
)
),
...
)