aws-sam-cli
aws-sam-cli copied to clipboard
Add mount option on sam local invoke/start-api
Describe your idea/feature/enhancement
Related to:
- https://github.com/aws/aws-sam-cli/pull/1486/files
- https://github.com/aws/aws-sam-cli/issues/1896
- https://github.com/aws/aws-sam-cli/issues/1485
We use custom lambda container images. We run code in /var/task/
or mount from EFS and run in /mnt/*
.
We can't emulate the /mnt
mount with SAM, or make changes to code mounted in /var/task
without a rebuild. This complicates dev - and makes dev impossible for builds with a big codebase.
The lambda runtime emulator works but is very limited.
Is there a workaround?
Proposal
It would be great to emulate the behaviour of docker --mount, with an extra function param:
From the example below:
sam local start-api --mount func=MyFunc,source="$(pwd)"/code,target=/mnt/shop
Additional Details
Example
- code/
-- foo.php
- bootstrap
- Dockerfile
- template.yaml
foo.php
<?php
echo json_encode(
[
'isBase64Encoded'=> false,
'statusCode' => 200,
'body' => '{"abc":123}'
]
);
bootstrap
#!/bin/bash
set -euo pipefail
while true
do
HEADERS="$(mktemp)"
EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
RESPONSE="$(mktemp)"
export EVENT_DATA
php /mnt/shop/foo.php >> "${RESPONSE}"
curl -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/${REQUEST_ID}/response" -d @${RESPONSE}
done
Dockerfile
FROM amazon/aws-lambda-provided:al2 as base
RUN yum install -y amazon-linux-extras
RUN amazon-linux-extras install epel -y
RUN rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm
RUN yum --enablerepo=remi-php74 install -y \
php-cli-7.4.14
COPY bootstrap /var/runtime
RUN chmod 755 /var/runtime/bootstrap
CMD [ "handler.php" ]
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
FileSystem:
Type: AWS::EFS::FileSystem
Properties: []
MountTarget:
Type: AWS::EFS::MountTarget
Properties: []
AccessPoint:
Type: AWS::EFS::AccessPoint
Properties: []
MyFunc:
Type: AWS::Serverless::Function
Metadata:
DockerContext: .
Dockerfile: Dockerfile
Properties:
PackageType: Image
FileSystemConfigs:
- Arn: !GetAtt AccessPoint.Arn
LocalMountPath: /mnt/shop
Events:
ApiEvent:
Type: Api
Properties:
Path: /path
Method: get
For reference - this is how we get around this issue:
https://github.com/dacgray/sam-local-start-api-container-image-volume-mount
Thanks for creating the feature request. I am tagging this for PM review and will update once we have discussed in team.
@c2tarun Any updates on this? This is currently a pretty significant drawback when using custom runtime container images, since any changes made to function code need a full rebuild of the runtime container. When using the built-in runtimes SAM detects changes to the function code and rebuilds the containers automatically.
/tmp
would also be a good choice for a mounted volume.
Agree with @BenVosper , this is a much needed feature.
Any progress regarding this request?
This is needed when using DevContainers. Or else it doesn't work.
Any update on this issue?
CC @hnnasit @mndeveci because you seem to be active. Looks like this issue might have gotten buried! Thanks for your help.
@c2tarun is there an update on the PM review? Is there a chance this feature will be implemented? Would be really good to have the possibility to mount volumes to, for example, emulate local EFS mounting.
I am interested in this feature because in the project I am working on there is a need to share files between lambdas executed as a part of one StepFunctions environment. When executed on AWS we use EFS for that.
But when testing functionality locally - there is no way (at least I'm not aware of it) to have a dir shared between different lambdas started by sam local start-lambda
For those running in devcontainer this solution worked for me
# get the host workspace path
host_workspace_path=$(docker inspect -f '{{ range .Mounts }}{{ if eq .Destination "/workspaces" }}{{ .Source }}{{ end }}{{ end }}' NAME_OR_ID)
# get the volume basedir
volume_basedir=$host_workspace_path/path-to-cdk-out
# now start sam local
sam local start-api --container-host host.docker.internal --docker-network NETWORK_NAME --docker-volume-basedir $volume_basedir