简体   繁体   中英

What should be run in a container for a PHP-based Docker AWS lambda?

PHP isn't a natively supported language in AWS Lambda, but I thought I'd try my hand at getting one working, using a custom Docker image. I am using this official AWS example to structure the image.

I don't quite understand the pieces yet. I will add what files I have to this post.

Firstly, my Dockerfile:

# Demo of a PHP-based lambda
#
# See example:
# https://github.com/aws-samples/php-examples-for-aws-lambda/blob/master/0.7-PHP-Lambda-functions-with-Docker-container-images/Dockerfile

FROM php:8.0-cli-alpine

WORKDIR /root

# Install Composer
COPY bin bin
RUN sh /root/bin/install-composer.sh
RUN php /root/composer.phar --version

# Install Composer deps
COPY composer.json composer.lock /root/
RUN php composer.phar install

# Install runtimes
COPY runtime /var/runtime
COPY src /var/task/

# Entrypoint
CMD ["index"]

Based on the example I also have:

  • A PHP listener program at /var/runtime/bootstrap (nearly verbatim copy of the example repo)
  • Composer dependencies at /root/vendor/... that are loaded by the bootstrap
  • A trivial index file at /var/task/index.php (verbatim copy of the example repo)

One change I have made is to base the image on an Alpine image from PHP, rather than to use an Amazon Linux image. I wonder, could there be something in the Amazon image that is needed?

The test I am using is the "hello world" in the AWS Lambda UI:

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

Anyway, I have used docker login and docker push to get the image to ECR. When I run the hello world test inside the AWS dashboard, I am getting this set of error logs in CloudWatch:

2021-11-13T19:12:12.449+00:00   IMAGE Launch error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied Entrypoint: [docker-php-entrypoint] Cmd: [index] WorkingDir: [/root]
2021-11-13T19:12:12.493+00:00   START RequestId: 38da1e10-4c93-4109-be10-32c58f83a2fb Version: $LATEST
2021-11-13T19:12:12.502+00:00   IMAGE Launch error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied Entrypoint: [docker-php-entrypoint] Cmd: [index] WorkingDir: [/root]
2021-11-13T19:12:12.504+00:00   END RequestId: 38da1e10-4c93-4109-be10-32c58f83a2fb
2021-11-13T19:12:12.504+00:00   REPORT RequestId: 38da1e10-4c93-4109-be10-32c58f83a2fb Duration: 9.20 ms Billed Duration: 10 ms Memory Size: 128 MB Max Memory Used: 3 MB
2021-11-13T19:12:12.504+00:00   RequestId: 38da1e10-4c93-4109-be10-32c58f83a2fb Error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied Runtime.InvalidEntrypoint 

That makes a lot of sense, as I don't understand the entry point of "index" either, but it's there as a CMD in the example Dockerfile. Is this an alias for something? I would be inclined to use something like php /var/runtime/bootstrap , but I'd rather understand things, rather than guessing.

I believe I might be able to use Lambda RIE to test this locally, but I wonder if that would tell me what I already know - I need to fix the CMD .

For what it's worth, I can't see how the index.php file is triggered in the lambda either. How does that get invoked?

Update

I am wondering if the parent image in the example ( public.ecr.aws/lambda/provided ) has an ENTRYPOINT that would shed some light on the apparently confusing CMD . I wonder if I will investigate that next.

Update 2

The ponderance that I might have to use the Amazon Linux image parent was a false steer -this official resource shows the use of standard Python and Node images.

I decided to try repairing the main Docker command:

CMD ["php", "/var/runtime/bootstrap"]

However it doesn't like that:

START RequestId: d95a29d3-6764-4bae-9976-09830c1c17af Version: $LATEST
IMAGE   Launch error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied Entrypoint: [docker-php-entrypoint] Cmd: [php,/var/runtime/bootstrap]   WorkingDir: [/root]
IMAGE   Launch error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied Entrypoint: [docker-php-entrypoint] Cmd: [php,/var/runtime/bootstrap]   WorkingDir: [/root]
END RequestId: d95a29d3-6764-4bae-9976-09830c1c17af
REPORT RequestId: d95a29d3-6764-4bae-9976-09830c1c17af  Duration: 19.88 ms  Billed Duration: 20 ms  Memory Size: 128 MB Max Memory Used: 3 MB   
RequestId: d95a29d3-6764-4bae-9976-09830c1c17af Error: fork/exec /usr/local/bin/docker-php-entrypoint: permission denied
Runtime.InvalidEntrypoint

Update 3

No matter what I do, I seem to run into problems with entrypoints. I've even tried a runtime script to chmod +x on the various binaries it doesn't like, but of course if I try to kick that off in the ENTRYPOINT , the container believes that /bin/sh cannot be executed. This is getting rather silly - containers are just not behaving correctly in the Lambda environment.

Update 4

I have now tried to move away from Alpine, in case a more standard OS will work correctly. No joy - I get the same. I'm now at the random-trying things point, and this is rather slow going, given that the build-push-install loop is cumbersome.

This question looks promising, but putting the bootstrap file in /var/task seems to go directly against the example I am working from.

This problem was tricksy because there were two major interlocking problems - a seemingly excessive permissions requirement, and what strikes me a massively non-standard use of the ENTRYPOINT/CMD systems.

Working solution

The Dockerfile that works is as follows:

# Demo of a PHP-based lambda
#
# See example:
# https://github.com/aws-samples/php-examples-for-aws-lambda/blob/master/0.7-PHP-Lambda-functions-with-Docker-container-images/Dockerfile

FROM php:8.0-cli-alpine

WORKDIR /root

# Install Composer
COPY bin bin
RUN sh /root/bin/install-composer.sh
RUN php /root/composer.phar --version

# Install Composer deps
COPY composer.json composer.lock /root/
# Move deps to /opt, /root has significant permission issues
RUN php /root/composer.phar install && \
    mv /root/vendor /opt/vendor

# Install runtimes
COPY runtime/bootstrap /var/runtime/
COPY src/index.php /var/task/

RUN chmod 777 /usr/local/bin/php /var/task/* /var/runtime/*

# The entrypoint seems to be the main handler
# and the CMD specifies what kind of event to process
WORKDIR /var/task
ENTRYPOINT ["/var/runtime/bootstrap"]
CMD ["index"]

So, that resolves one of my nagging questions about Amazon Linux - it is not required. Note that although I installed Composer dependencies in /root , they could not stay there - even 777 perms on them seemed to be insufficient.

As you can see I used 777 permissions on things in /var . 755 might work, maybe even 750 would work - but the key here is that Amazon appears to be a user that is not the build (root) user. That tripped me up a lot.

Now the ENTRYPOINT is used to run the bootstrap script, which appears to be doing general mediation between events on the AWS side and "use cases" in /var/tasks . The normal purpose of a Docker entrypoint is as a command wrapper to CMD , so to use CMD as a "default lambda type" seems to significantly violate the principle of least surprise. I would have thought the lambda type would be defined by the incoming event, not by any lambda-side setting.

Testing

To test this lambda I use this event in the Lambda UI:

{
  "queryStringParameters": { "name": "halfer" }
}

And the demo code will respond with:

{
  "statusCode": 200,
  "headers": {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Headers": "Content-Type",
    "Access-Control-Allow-Methods": "OPTIONS,POST"
  },
  "body": "Hello, halfer"
}

Suffice it to say this feels rather brittle. Admittedly the demo code is not production quality, but even so, I suspect this would need a pipeline to do a real AWS Lambda test prior to merging down or deployment.

Performance

Here is why lambdas are tempting, especially for infrequent calls such as crons - they are instantiated quickly and die quickly, leaving no running infra. In one of my demo calls I have:

Init duration     188.75 ms
Duration           39.45 ms
Billed duration   229 ms

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM