Home > Software engineering >  AWS Lambda Python Docker image: connection reset by peer / timeout
AWS Lambda Python Docker image: connection reset by peer / timeout

Time:10-09

I am trying to deploy a function that converts strings into vectors to AWS Lambda:

def _encode(text: str):
  [<main functionality>]

@lru_cache
def encode(text: str):
    return _encode(text)



def handler(event, context):
    return encode(event["text"])

This function works as expected when I call it in the Python shell:

import app
app.handler({"text"}, None)

<expected result>

The encode() functionally actually is complex and requires external dependencies (>1GB) which is why I am going for the Docker image approach as described in the documentation. This is my Dockerfile:

FROM amazon/aws-lambda-python:3.9


# Install requirements
RUN python -m pip install --upgrade pip
COPY requirements.txt ${LAMBDA_TASK_ROOT}
RUN python -m pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"


# Copy app
COPY app.py ${LAMBDA_TASK_ROOT}

CMD [ "app.handler" ]

Build the Docker image and run it:

$ docker build -t my-image:latest .
[...]
Successfully built xxxx
Successfully tagged my-image:latest

$ docker run -p 9000:8000 my-image:latest 
time="2021-10-07T10:12:13.165" level=info msg="exec '/var/runtime/bootstrap' (cwd=/var/task, handler=)"

So I try to test the function locally with curl, following the testing documentation:

$ curl  -XPOST  "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{ }'
curl: (56) Recv failure: Connection reset by peer

I've also tried passing the expected argument like this:

curl -XPOST  "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{ "text": "text" }'
curl: (56) Recv failure: Connection reset by peer

Or in a stringified Json in the body field, as described in this blog:

$ curl -XPOST  "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{ "body":  "{ \"text\": \"text\"}" }'
curl: (56) Recv failure: Connection reset by peer

Assuming a local failure, I've pushed the image to AWS ECR and created a lambda function. I've created a test in the AWS Lambda console:

{
  "text": "doc"
}

When I run the test in the AWS Lambda Console, it times out, even after increasing the timeout to 60s. Locally, the function takes less than 1 second to execute.

My first question is: how can I properly test and debug my Lambda function/Docker image locally? Is there a way to increase the log verbosity for the container, as I don't see any logs after the initial startup?

And, more specifically, am I missing anything in the Dockerfile and/or my Lambda function handler? I've been following the documentation, but the specifics of the CMD entry is not very clear. Therefore, I stick with the naming conventions defined there, but perhaps I additionally need to set an ENTRYPOINT or some other Docker command?

I am also not sure that the issue is the same on AWS Lambda as on my locally running image. Only the timeout is logged, I don't see how to get to the root cause.

CodePudding user response:

While I still would like to have a better way for debugging, it turns out that this issue was simply due to an incorrect port mapping. The service runs on port 8080, not on port 8000 inside the container. So the correct command for running the image is:

$ docker run -p 9000:8080 my-image:latest
  • Related