[英]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:基于这个例子,我还有:
/var/runtime/bootstrap
(nearly verbatim copy of the example repo) /var/runtime/bootstrap
的 PHP 侦听器程序(几乎是示例存储库的逐字副本)/root/vendor/...
that are loaded by the bootstrap/root/vendor/...
中的 Composer 依赖项/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 login
和docker 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?它是如何被调用的?
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.我想知道我接下来是否会调查。
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
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 环境中行为不正确。
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 系统的大量非标准使用。
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 端设置定义。
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 测试。
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.