Skip to content

fix(local invoke): ensure later Lambda layers overwrite earlier layers in Docker image#8688

Merged
roger-zhangg merged 3 commits intodevelopfrom
layer_fix_3
Feb 24, 2026
Merged

fix(local invoke): ensure later Lambda layers overwrite earlier layers in Docker image#8688
roger-zhangg merged 3 commits intodevelopfrom
layer_fix_3

Conversation

@roger-zhangg
Copy link
Copy Markdown
Member

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

  • `samcli/local/docker/lambda_image.py`: Changed `_generate_dockerfile` to stage layers via cp -rf
  • `tests/unit/local/docker/test_lambda_image.py`: Updated expected Dockerfile output in unit tests
  • `tests/integration/local/invoke/test_integrations_cli.py`: Added tearDownClass image cleanup"

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

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.
@roger-zhangg roger-zhangg requested a review from a team as a code owner February 23, 2026 20:44
@roger-zhangg
Copy link
Copy Markdown
Member Author

valerena
valerena previously approved these changes Feb 23, 2026
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"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

reedham-aws
reedham-aws previously approved these changes Feb 23, 2026
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.
@roger-zhangg roger-zhangg dismissed stale reviews from reedham-aws and valerena via 6dd935a February 24, 2026 00:20
@roger-zhangg
Copy link
Copy Markdown
Member Author

Added an addtional test to import 2 layers and test function from both
integ test triggered: https://github.com/aws/aws-sam-cli/actions/runs/22330860970

Also for the first layer, still use Add directly for better performance.
We only need to handle overwrite issue on the second / or later layers.

@roger-zhangg
Copy link
Copy Markdown
Member Author

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.
@roger-zhangg roger-zhangg added this pull request to the merge queue Feb 24, 2026
Merged via the queue into develop with commit 033b787 Feb 24, 2026
63 of 64 checks passed
@roger-zhangg roger-zhangg deleted the layer_fix_3 branch February 27, 2026 23:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants