原文🔗:https://docs.aws.amazon.com/lambda/latest/dg/images-create.html
AWS 提供了一系列的开源基础的 base images,让我们来创建自己的容器 image。这些基础的 images 里包括了一个 实时客户端( runtime interface client )来管理 Lambda 和你的函数代码的交互。
比如这个网址有包括一个 Node.js 和一个 Python 的例子: Container image support for Lambda。
主题:
- Base images for Lambda ——基础的 images
- Testing Lambda container images locally ——本地测试
- Prerequisites ——之前必须有的
- Image types ——image类型
- Container tools ——容器工具
- Container image settings ——容器 image 设置
- Creating images from AWS base images ——从 AWS 基础 images 创建 images
- Creating images from alternative base images ——从可选的(替代的)基础 images 创建 images
- Upload the image to the Amazon ECR repository ——把 image 上传到 Amazon ECR 仓库
- Create an image using the AWS SAM toolkit ——用 AWS SAM 工具箱来创建 image
Prerequisites
先决条件
要在 Lambda 上部署一个 container image, 你需要 AWS CLI 和 Docker CLI( AWS CLI and Docker CLI)。额外的,请注意以下条件:
- container image 必须要集成了 Lambda 的 Runtime API。AWS 里开源的 实时接口有集成,所以你可以添加一个这个事实交互客户端到你更接近的 basic image 中去让它支持 Lambda。
- container image 需要能够在 只读文件系统(read-only file system)中运行。你的函数代码能够获取到一个可写的 /tmp 目录,大概 512 MB 到 10,240 MB之间,按 1MB递增的存储空间。(并不是很理解,意思是空间留大一点?)
- 权限问题:默认的 Lambda用户必须能够读所有需要的文件去运行你的函数代码。Lambda 采用了安全性的最佳实践,即定义了一个有着最小 权限的(least-privileged permissions)默认的 Linux 用户。所以你要确认一下你的应用代码不需要依赖一些其他 Linux 用户无法访问的文件去运行。
- Lambda 支持 只有 Linux-based 的 container images。
- Lambda 提供 多架构的 基础 images。但是你为你的函数构建的 image 必须指定其中一种。Lambda 不支持用了多架构的container images。(意思是支持多种,但具体到一个上不能跨架构。)
Image types
镜像类型
你可以用一个 AWS 提供好的 基础镜像模版之类的来创建,比如 Alpine 或 Debian。Lambda 支持满足一下两个 image 显示格式的任意 image:
- Docker image manifest V2, schema 2 (used with Docker version 1.10 and newer)
- Open Container Initiative (OCI) Specifications (v1.0.0 and up)
Container tools
容器工具
为了创建 container image,你需要用任意一个开发工具支持上面的显示格式。
比如你可以用 Docker CLI 来构建、测试和部署你的容器images。
Container image settings
容器镜像设置
Lambda 支持在 Dockerfile 中设置:
- ENTRYPOINT – Specifies the absolute path to the entry point of the application. ——进入点,明确进入应用的绝对路径
- CMD – Specifies parameters that you want to pass in with ENTRYPOINT. ——明确你要和进入点一起传的参数
- WORKDIR – Specifies the absolute path to the working directory. —— 明确工作目录的绝对路径
- ENV – Specifies an environment variable for the Lambda function. ——明确 Lambda 函数的环境变量
参考链接:ENTRYPOINT、 Demystifying ENTRYPOINT and CMD in Docker
你可以在 Dockerfile 中就明确这些设置,也可以用 Lambda 终端或 Lambda API 来重写覆盖掉这些配置。这让你能够部署同一个容器镜像里的多个函数,用不同的运行配置(runtime configurations)。
Creating images from AWS base images
从 AWS base images 创建 images
为了一个新的 Lambda函数建 container image 的时候,你可以从 AWS base image for Lambda 开始。Lambda 提供了两种类型的基础镜像:
- Multi-architecture base imageSpecify one of the main image tags (such as
python:3.9orjava:11) to choose this type of image. - Architecture-specific base imageSpecify an image tag with an architecture suffix. For example, specify
3.9-arm64to choose the arm64 base image for Python 3.9.
(我感觉课程上用第二种就可以了。)
也可以从其他的容器注册处(alternative base image from another container registry)使用替代的 base image。加入前面说过的 开源运行交互客户端就可以了。
Note:
AWS 阶段性的提供更新,如果你的 Dockerfile 在 FROM 属性下包括了 image 名字,你的 Docker客户端会从 Amazon ECR 仓库里拉取最新版本的 image。为了用最新的 base image,你必须重构你的容器镜像,并更新函数代码(update the function code)。
具体步骤:
- 在本地机器,为你的新函数(new func)创建一个项目目录(project directory)。
- 在 project directory 下创建一个叫
app的目录,然后把 function handler code 添加到 app 目录下。 - 用 文本编辑器创建一个新的 Dockerfile。 AWS 提供两个环境变量:
- LAMBDA_TASK_ROOT=/var/task
- LAMBDA_RUNTIME_DIR=/var/runtime
在 ${LAMBDA_TASK_ROOT} 目录下安装依赖。它和 handler 是平级的,以保证运行的时候可以定位到。
下面是 Dockerfile 的例子:
FROM public.ecr.aws/lambda/python:3.8
# Copy function code COPY app.py ${LAMBDA_TASK_ROOT}
# Install the function's dependencies using file requirements.txt
# from your project folder. COPY requirements.txt . RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) CMD [ "app.handler" ]
4. 用 docker build 命令创建 image,跟着一个名字,比如创还能了一个叫 hello-world 的镜像:
docker build -t hello-world .
5. 用 run 来开启 Docker 镜像,接上例:
docker run -p 9000:8000 hello-world
6. (可选)用 runtime interface emulator 测试一下你的应用。打开另一个新的终端窗口,用 curl 提交一个事件给下来的 endpoint:
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
这个命令会调 container image 里的函数,并返回响应。
Creating images from alternative base images
前提:AWS CLI + Docker Desktop + function code
步骤和上面的很像。前面多了一步找一个 base image,如 Alpine, Debian和 Ubuntu。
然后创项目目录,创 app目录,加 handler 代码。
不一样的地方来了,Dockerfile 有所不同:
- FROM 属性 , 设置成 base image 的 URI。
- 添加命令安装 runtime interface client。
- ENTRYPOINT 来调用 runtime interface client。
- CMD 明确 Lambda function handler, 和上面的一样。
例子:
# Define function directory
ARG FUNCTION_DIR="/function"
FROM python:buster as build-image
# Install aws-lambda-cpp build dependencies
RUN apt-get update && \
apt-get install -y \
g++ \
make \
cmake \
unzip \
libcurl4-openssl-dev
# Include global arg in this stage of the build
ARG FUNCTION_DIR
# Create function directory
RUN mkdir -p ${FUNCTION_DIR}
# Copy function code
COPY app/* ${FUNCTION_DIR}
# Install the runtime interface client
RUN pip install \
--target ${FUNCTION_DIR} \
awslambdaric
# Multi-stage build: grab a fresh copy of the base image
FROM python:buster
# Include global arg in this stage of the build
ARG FUNCTION_DIR
# Set working directory to function root directory
WORKDIR ${FUNCTION_DIR}
# Copy in the build image dependencies
COPY --from=build-image ${FUNCTION_DIR} ${FUNCTION_DIR}
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
CMD [ "app.handler" ]
5. 一样的命令 build 就好了。
Upload the image to the Amazon ECR repository
把 image 上传到 亚马逊的 ECR 仓库
在 Amazon ECR,如果你重新把 image tag 给了另一个 image,Lambda不会更新版本的。
123456789012 要替换成你自己的 AWS 账户ID,设置 region value 到你想创建的 region。(那设置时区会影响另一个时区的人使用吗?今天看的 FSDL 的 Lec 09 讲到不同的时区会有不同的 CO2 排放量,哇,神奇的角度)
- 将 Docker CLI 验证注册到 Amazon ECR registry:
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
- 用
create-repository命令在 Amazon ECR 创建仓库:aws ecr create-repository --repository-name hello-world --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
3. 标记 image 和你的仓库匹配,然后用 docker push 命令部署到 Amazon ECR:
docker tag hello-world:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
你的容器镜像已经在 Amazon ECR 容器注册过了,你就可以 create and run Lambda函数了! Finally!
最后又提供了一个 AWS Serverless Application Model (AWS SAM) 工具箱来创建。用 AWS SAM CLI init 命令来设置项目的脚手架。
在 AWS SAM 模版中,设置 Runtime type 到 Image,提供 base image 的 URI 就可以了。
更多请看:Building applications (AWS Serverless Application Model Developer Guide.)
