Skip Docker Lambda image builds when ImageUri is a valid ECR location
See original GitHub issueDescribe your idea/feature/enhancement
When configuring a lambda / serverless function of which the PackageType
is Zip
, SAM preemptively checks whether the resource CodeUri
is a S3 location or not.
# This function is already packaged and will to be ignored by SAM
Function:
Type: AWS::Serverless::Function
Properties:
PackageType: Zip
CodeUri: s3://bucket/function.zip
...
If so, SAM will not attempt to build said lambda, and will show a warning to the user:
% sam build
The resource AWS::Serverless::Function 'Function' has specified S3 location for CodeUri. It will not be built and SAM CLI does not support invoking it locally.
I would expect SAM to do the same when attempting to build a PackageType: Image
lambda function; checking whether or not the resource property ImageUri
is a valid ECR URL before attempting to build said images locally, yet this feature is not supported by SAM today:
# SAM should not attempt to build this Lambda
Function:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
ImageUri: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/function:latest
Instead, attempting to do so will most likely output the following exception (as the DockerContext
resource metadata, required for building Docker Images using SAM, will most likely be unset, error traced here):
% sam build
Building image for Function function
Traceback (most recent call last):
File "/usr/local/bin/sam", line 8, in <module>
sys.exit(cli())
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/click/decorators.py", line 73, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/samcli/lib/telemetry/metric.py", line 153, in wrapped
raise exception # pylint: disable=raising-bad-type
File "/usr/local/lib/python3.8/site-packages/samcli/lib/telemetry/metric.py", line 122, in wrapped
return_value = func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/samcli/lib/utils/version_checker.py", line 42, in wrapped
actual_result = func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/samcli/cli/main.py", line 90, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/samcli/commands/build/command.py", line 210, in cli
do_cli(
File "/usr/local/lib/python3.8/site-packages/samcli/commands/build/command.py", line 315, in do_cli
artifacts = builder.build()
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/app_builder.py", line 169, in build
return build_strategy.build()
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/build_strategy.py", line 41, in build
result.update(self._build_functions(self._build_graph))
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/build_strategy.py", line 52, in _build_functions
function_build_results.update(self.build_single_function_definition(build_definition))
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/build_strategy.py", line 118, in build_single_function_definition
result = self._build_function(
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/app_builder.py", line 500, in _build_function
return self._build_lambda_image(function_name=function_name, metadata=metadata) # type: ignore
File "/usr/local/lib/python3.8/site-packages/samcli/lib/build/app_builder.py", line 322, in _build_lambda_image
docker_context_dir = pathlib.Path(self._base_dir, docker_context).resolve()
File "/usr/local/Cellar/python@3.8/3.8.10/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 1042, in __new__
self = cls._from_parts(args, init=False)
File "/usr/local/Cellar/python@3.8/3.8.10/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 683, in _from_parts
drv, root, parts = self._parse_args(args)
File "/usr/local/Cellar/python@3.8/3.8.10/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py", line 667, in _parse_args
a = os.fspath(a)
As a result, it is currently not possible to deploy Docker-packed Lambda functions, without building the underlying image using SAM, which is, in my opinion, very limiting (e.g., inability to share ECR registries & images among an Organization, inability to use Docker images that require a specific build workflow -passing secrets using buildkit, environment specific args-…)
I did find a workaround, tricking SAM into skipping the build of a PackageType: Image
Lambda, by setting the Code.S3Bucket
property to an empty value, but I believe this to be very hack-y:
# A working hack to skip the build of a Image Lambda function
Function:
Type: AWS::Lambda::Function
Properties:
PackageType: Image
Code:
S3Bucket: !Ref AWS::NoValue
ImageUri: 123456789012.dkr.ecr.eu-west-1.amazonaws.com/function:latest
Proposal
- Similarly to
Zip
packaged lambdas, check whether or not theImageUri
property of aAWS::Serverless::Function
, orCode.ImageUri
property of aAWS::Lambda::Function
is a valid ECR URL before attempting to locally build said function. This could be done by reusing a function in thepackage.ecr_utils
module here. - Show the user a proper warning when skipping the build of Docker lambda images.
Things to consider:
- Will this require any updates to the SAM Spec
Additional Details
A PR should follow soon with a workaround proposal.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:8
- Comments:12 (4 by maintainers)
Hi,
I haven’t contributed to SAM before, but is there any way I can help move this along? I’m happy to help with any work that needs to be done.
This has been an issue at my company. We have lambda function container images that host machine learning models that can be used in multiple SAM stacks. When I bumped into this issue a couple of months ago I came here with the intent of opening a feature request but found this one had just been opened. I’ve been silently watching its progress but my impatience got the better of me. (That and my current workaround is a private fork with a very similar solution… not ideal.)
Anyway, my apologies if these things simply take time but do let me know if I can contribute/test/whatever to help.
Thanks, Mike “Moose” Moustakas
I’m not convinced this issue is fully resolved. In fact, the solution implemented in #2935 has introduced a regression for us.
This issue requests that the following isn’t built:
However, why would this preclude SAM from being able to invoke the lambda locally if the docker image already exists in the local image cache?
We are using SAM to integration test lambdas that are built from multiple projects. There is no build or deploy being performed, just a local test of the lambda functions and the step function state machine that wires it all together. But now we are getting the following error when things used to work fine:
The resource AWS::Serverless::Function 'SetupFunction' has specified ECR registry image for ImageUri. It will not be built and SAM CLI does not support invoking it locally.