'AWS SAM-lambda: Cannot import from parent directory containing a fastapi app

I'm trying to deploy a fastapi application to AWS lambda using the SAM client. The issue is that I cannot get Lambda to recognize the parent folder.

I have a fastapi app structure that is based on this, straight from the fastapi docs. With this app structure, I set up a SAM lambda dockerfile like so:

FROM public.ecr.aws/lambda/python:3.8

RUN yum -y install file-devel
COPY requirements.txt  .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" && rm requirements.txt
COPY ./app ${LAMBDA_TASK_ROOT}
CMD ["app.main.handler"]

Then within the template file I've set

    Handler: app.main.handler

among the other settings.

I run the SAM build, then sam local start-api, and hit the /docs endpoint. But SAM complains:

> sam local start-api

Mounting at http://127.0.0.1:3000/{proxy+} [DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2022-04-28 12:07:53  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
Invoking Container created from myapp:sam-lambda
Image was not found.
Removing rapid images for repo myapp
Building image.................
Skip pulling image and use local one: myapp:rapid-1.43.0-x86_64.

START RequestId: 793d031e-ad4a-431d-a9a7-7dd5744f2bef Version: $LATEST
Traceback (most recent call last): Unable to import module 'app.main': No module named 'app'
END RequestId: 793d031e-ad4a-431d-a9a7-7dd5744f2bef
REPORT RequestId: 793d031e-ad4a-431d-a9a7-7dd5744f2bef  Init Duration: 0.20 ms  Duration: 120.60 ms Billed Duration: 121 ms Memory Size: 10000 MB   Max Memory Used: 10000 MB
Lambda returned empty body!
Invalid lambda response received: Invalid API Gateway Response Keys: {'errorMessage', 'stackTrace', 'errorType'} in {'errorMessage': "Unable to import module 'app.main': No module named 'app'", 'errorType': 'Runtime.ImportModuleError', 'stackTrace': []}
2022-04-28 12:08:03 127.0.0.1 - - [28/Apr/2022 12:08:03] "GET /docs HTTP/1.1" 502 -

I suspect I need to set the proper path somewhere, or the PYTHONPATH, but I've tried a million combinations. It seems like the app directory itself is not recognized by python within the container, maybe because it is a level above what the docker container can see? All my routes throughout the fastapi app are pegged to the parent app/ folder, e.g.

from app.main import handler

etc...

Any help is appreciated.



Solution 1:[1]

Answering my own question for anybody that stumbles upon this:

The original problem was caused by another directory in the application that was not added.

Changing the Dockerfile to this:

FROM public.ecr.aws/lambda/python:3.8

RUN yum -y install file-devel
COPY requirements.txt  .
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" && rm requirements.txt
COPY . ${LAMBDA_TASK_ROOT}
CMD ["app.main.handler"]

was one way to solve it.

However, the truly brutal part about this was that SAM lambda has a quirk when using Docker custom container. If you run

sam build --use-container 
sam local start-api

your changes won't be reflected! What you need is this flag:

sam build --use-container 
sam local start-api --force-image-build

This was what burned most of my time. Always use the --force-image-build flag when using your own Dockerfile with SAM.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 John Kealy