fix(local invoke): ensure later Lambda layers overwrite earlier layers in Docker image#8688
fix(local invoke): ensure later Lambda layers overwrite earlier layers in Docker image#8688roger-zhangg merged 3 commits intodevelopfrom
Conversation
Docker's ADD/COPY with directories may merge rather than overwrite files in BuildKit, breaking AWS Lambda's layer precedence where later layers should override earlier ones. Fix by staging each layer in a temp directory and using 'cp -rf' to explicitly overwrite files in /opt, matching real Lambda behavior. Also add cleanup_samcli_images() call to tearDownClass for proper cleanup between parameterized test classes.
| docker_patch.from_env.return_value = docker_client_mock | ||
|
|
||
| expected_docker_file = "FROM python\nADD aws-lambda-rie-arm64 /var/rapid/\nRUN mv /var/rapid/aws-lambda-rie-arm64 /var/rapid/aws-lambda-rie && chmod +x /var/rapid/aws-lambda-rie\nADD layer1 /opt\n" | ||
| expected_docker_file = "FROM python\nADD aws-lambda-rie-arm64 /var/rapid/\nRUN mv /var/rapid/aws-lambda-rie-arm64 /var/rapid/aws-lambda-rie && chmod +x /var/rapid/aws-lambda-rie\nADD layer1 /tmp/layer0\nRUN cp -rf /tmp/layer0/. /opt/ && rm -rf /tmp/layer0\n" |
There was a problem hiding this comment.
Do we have something in the integration tests that checks that 2 layers are built correctly? (is it the test that you mention in the description?).
It's interesting that we don't have a unit test that checks the behavior with 2 or more layers, but if we have an integration test that checks that, then it should be good enough.
There was a problem hiding this comment.
This is a good point, it seems we were checking the layer override (this test). But not really 2 layer working together. I can take a look
Docker's ADD with directories may not overwrite existing files in all build backends (e.g. BuildKit). This breaks AWS Lambda's layer precedence where later layers should override earlier ones. Fix: the first layer still uses ADD directly to /opt. Subsequent layers are staged in a temp directory and copied with 'cp -rf' to guarantee overwrite semantics. Also adds test_two_independent_layers integration test that verifies two layers providing different modules both work in a single function, and adds cleanup_samcli_images() to tearDownClass.
6dd935a
|
Added an addtional test to import 2 layers and test function from both Also for the first layer, still use Add directly for better performance. |
|
Seems new integ test is failing, fixing |
The nested template parents were not forwarding the new layer parameters, causing SAM CLI to use the default fake ARNs and fail with lambda:GetLayerVersion permission errors.
Problem
When a function has multiple layers with overlapping files (e.g. both layer1 and layer2 provide `simple_python_module/simple_python.py`), the second layer should win per AWS Lambda semantics. However, Docker's `ADD layer2 /opt` after `ADD layer1 /opt` does not reliably overwrite files in all build backends (BuildKit vs legacy builder).
This caused `test_download_two_layers` to fail with `"Layer1" != "Layer2"`.
Fix
Stage each layer in a unique temp directory (`/tmp/layer0`, `/tmp/layer1`, etc.) and use `RUN cp -rf /tmp/layerN/. /opt/ && rm -rf /tmp/layerN` to explicitly overwrite files, matching real Lambda behavior.
Also adds `cleanup_samcli_images()` call to `tearDownClass` for proper image cleanup between parameterized test classes.
Changes
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.