aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.49k stars 1.17k forks source link

Add mount option on sam local invoke/start-api #2589

Open dacgray opened 3 years ago

dacgray commented 3 years ago

Describe your idea/feature/enhancement

Related to:

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
dacgray commented 3 years ago

For reference - this is how we get around this issue:

https://github.com/dacgray/sam-local-start-api-container-image-volume-mount

c2tarun commented 2 years ago

Thanks for creating the feature request. I am tagging this for PM review and will update once we have discussed in team.

BenVosper commented 2 years ago

@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.

Sparticuz commented 2 years ago

/tmp would also be a good choice for a mounted volume.

dschiavu commented 1 year ago

Agree with @BenVosper , this is a much needed feature.

Lucas1983 commented 1 year ago

Any progress regarding this request?

ffMathy commented 1 year ago

This is needed when using DevContainers. Or else it doesn't work.

BenVosper commented 10 months ago

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.

VladyslavXXI commented 4 months ago

@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

wyliang commented 2 weeks ago

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