I am trying to run a shell script in AWS Lambda. I packaged it in a Docker image based on Alpine. The logs show that it runs fine, but the Lambda shows an error, even though my script exited with 0.
This blog post was my key to understanding what went wrong.
The docs page I had found mentioned the Lambda Runtime API, and how the container needs to implement that API. But that didn’t make enough sense to me.
The gist of it was that my container was running a script to do one thing and exit. However, the script needs to let Lambda determine when to stop, and it needs to continue to execute the business logic while there’s more executions in the Lambda queue.
The relevant piece of the blog post was this part of the script:
...
while true
do
# Create a temporary file
HEADERS="$(mktemp)"
# Get an event. The HTTP request will block until one is received
EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
# Extract request ID by scraping response headers received above
REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
############################
# Run my arbitrary program #
############################
/businesscode.sh
############################
# Send the response
curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d '{"statusCode": 200}'
done
To liken this to a Go lambda in a zip file, anything occuring before the while true
is like the func init() {}
in Go. It’s the startup logic for cold
starts. Anything in the loop is what is run when the Lambda is called.
This loop watches the queue, and notifies the API the result of each call.