简体   繁体   English

应该在基于 PHP 的 Docker AWS lambda 的容器中运行什么?

[英]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. PHP 不是 AWS Lambda 中本机支持的语言,但我想我会尝试使用自定义 Docker 映像来使其工作。 I am using this official AWS example to structure the image.我正在使用这个官方 AWS 示例来构建图像。

I don't quite understand the pieces yet.我还不太明白这些片段。 I will add what files I have to this post.我将在这篇文章中添加我拥有的文件。

Firstly, my Dockerfile:首先,我的 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) /var/runtime/bootstrap的 PHP 侦听器程序(几乎是示例存储库的逐字副本)
  • Composer dependencies at /root/vendor/... that are loaded by the bootstrap引导程序加载的/root/vendor/...中的 Composer 依赖项
  • A trivial index file at /var/task/index.php (verbatim copy of the example repo) /var/task/index.php一个简单索引文件(示例 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.我所做的一项更改是将映像基于来自 PHP 的 Alpine 映像,而不是使用 Amazon Linux 映像。 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:我使用的测试是 AWS Lambda UI 中的“hello world”:

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

Anyway, I have used docker login and docker push to get the image to ECR.无论如何,我已经使用docker logindocker push将图像发送到 ECR。 When I run the hello world test inside the AWS dashboard, I am getting this set of error logs in CloudWatch:当我在 AWS 仪表板中运行 hello world 测试时,我在 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.这很有意义,因为我也不理解“索引”的入口点,但它在示例 Dockerfile 中作为CMD存在。 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.我倾向于使用类似php /var/runtime/bootstrap东西,但我宁愿理解事物,而不是猜测。

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 .我相信我可以使用Lambda RIE在本地测试这个,但我想知道这是否会告诉我我已经知道的 - 我需要修复CMD

For what it's worth, I can't see how the index.php file is triggered in the lambda either.对于它的价值,我也看不到index.php文件是如何在 lambda 中触发的。 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 .我想知道示例中的父图像 ( public.ecr.aws/lambda/provided ) 是否有一个ENTRYPOINT可以阐明显然令人困惑的CMD I wonder if I will investigate that next.我想知道我接下来是否会调查。

Update 2更新 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.我可能不得不使用 Amazon Linux 映像父级的想法是错误的转向 -此官方资源显示了标准 Python 和 Node 映像的使用。

I decided to try repairing the main Docker command:我决定尝试修复主要的 Docker 命令:

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更新 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.我什至尝试了一个运行时脚本在它不喜欢的各种二进制文件上chmod +x ,但是当然,如​​果我尝试在ENTRYPOINT启动它,容器认为/bin/sh无法执行。 This is getting rather silly - containers are just not behaving correctly in the Lambda environment.这变得相当愚蠢 - 容器在 Lambda 环境中行为不正确。

Update 4更新 4

I have now tried to move away from Alpine, in case a more standard OS will work correctly.我现在试图远离 Alpine,以防更标准的操作系统能够正常工作。 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. 这个问题看起来很有希望,但是将引导文件放在/var/task似乎直接与我正在使用的示例背道而驰。

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.这个问题很棘手,因为有两个主要的连锁问题——一个看似过度的权限要求,以及让我印象深刻的是对 ENTRYPOINT/CMD 系统的大量非标准使用。

Working solution工作解决方案

The Dockerfile that works is as follows:工作的 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/
# 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.因此,这解决了我关于 Amazon Linux 的一个烦人的问题——这不是必需的。 Note that although I installed Composer dependencies in /root , they could not stay there - even 777 perms on them seemed to be insufficient.请注意,虽然我在/root安装了 Composer 依赖项,但它们不能留在那里 - 即使它们上的777 perms 似乎也不够。

As you can see I used 777 permissions on things in /var .如您所见,我对/var内容使用了 777 权限。 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. 755 可能有效,甚至 750 也可能有效 - 但这里的关键是亚马逊似乎是一个不是构建(root)用户的用户。 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 .现在ENTRYPOINT用于运行引导脚本,该脚本似乎在 AWS 端的事件和/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. Docker 入口点的正常用途是作为CMD的命令包装器,因此将CMD用作“默认 lambda 类型”似乎严重违反了最小意外原则。 I would have thought the lambda type would be defined by the incoming event, not by any lambda-side setting.我原以为 lambda 类型将由传入事件定义,而不是由任何 lambda 端设置定义。

Testing测试

To test this lambda I use this event in the Lambda UI:为了测试这个 lambda,我在 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.诚然,演示代码不是生产质量,但即便如此,我怀疑这需要一个管道在合并或部署之前进行真正的 AWS Lambda 测试。

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.这就是为什么 lambda 很诱人的原因,尤其是对于 cron 之类的不频繁调用 - 它们被快速实例化并迅速消亡,没有运行基础设施。 In one of my demo calls I have:在我的一次演示电话中,我有:

Init duration     188.75 ms
Duration           39.45 ms
Billed duration   229 ms

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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