

# 使用容器映像部署 .NET Lambda 函数
<a name="csharp-image"></a>

有三种方法可以为 .NET Lambda 函数构建容器映像：
+ [使用 .NET 的 AWS 基本映像](#csharp-image-instructions)

  [AWS 基本映像](images-create.md#runtimes-images-lp)会预加载一个语言运行时系统、一个用于管理 Lambda 和函数代码之间交互的运行时系统接口客户端，以及一个用于本地测试的运行时系统接口仿真器。
+ [使用 AWS 仅限操作系统的基础镜像](images-create.md#runtimes-images-provided)

  [AWS 仅限操作系统的运行时系统](https://gallery.ecr.aws/lambda/provided)包含 Amazon Linux 发行版和[运行时系统接口模拟器](https://github.com/aws/aws-lambda-runtime-interface-emulator/)。这些镜像通常用于为编译语言（例如 [Go](go-image.md#go-image-provided) 和 [Rust](lambda-rust.md)）以及 Lambda 未提供基础映像的语言或语言版本（例如 Node.js 19）创建容器镜像。您也可以使用仅限操作系统的基础映像来实施[自定义运行时系统](runtimes-custom.md)。要使映像与 Lambda 兼容，您必须在映像中包含 [.NET 的运行时系统接口客户端](#csharp-image-clients)。
+ [使用非 AWS 基本映像](#csharp-image-clients)

  您还可以使用其他容器注册表的备用基本映像，例如 Alpine Linux 或 Debian。您还可以使用您的组织创建的自定义映像。要使映像与 Lambda 兼容，您必须在映像中包含 [.NET 的运行时系统接口客户端](#csharp-image-clients)。

**提示**  
要缩短 Lambda 容器函数激活所需的时间，请参阅 Docker 文档中的[使用多阶段构建](https://docs.docker.com/build/building/multi-stage/)。要构建高效的容器映像，请遵循[编写 Dockerfiles 的最佳实践](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)。

此页面介绍了如何为 Lambda 构建、测试和部署容器映像。

**Topics**
+ [AWS.NET 的基本映像](#csharp-image-base)
+ [使用 .NET 的 AWS 基本映像](#csharp-image-instructions)
+ [将备用基本映像与运行时系统接口客户端配合使用](#csharp-image-clients)

## AWS.NET 的基本映像
<a name="csharp-image-base"></a>

AWS 为 .NET 提供了以下基本映像：


| 标签 | 运行时 | 操作系统 | Dockerfile | 弃用 | 
| --- | --- | --- | --- | --- | 
| 10 | .NET 10 | Amazon Linux 2023 | [GitHub 上适用于 .NET 10 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet10/Dockerfile.dotnet10) |   2028 年 11 月 14 日   | 
| 9 | .NET 9 | Amazon Linux 2023 | [GitHub 上适用于 .NET 9 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet9/Dockerfile.dotnet9) |   2026 年 11 月 10 日   | 
| 8 | .NET 8 | Amazon Linux 2023 | [GitHub 上适用于 .NET 8 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet8/Dockerfile.dotnet8) |   2026 年 11 月 10 日   | 

Amazon ECR 存储库：[gallery.ecr.aws/lambda/dotnet](https://gallery.ecr.aws/lambda/dotnet)

## 使用 .NET 的 AWS 基本映像
<a name="csharp-image-instructions"></a>

### 先决条件
<a name="dotnet-csharp-image-prerequisites"></a>

要完成本节中的步骤，您必须满足以下条件：
+ [.NET 开发工具包](https://dotnet.microsoft.com/download) – 以下步骤使用 .NET 8 基本映像。确保 .NET 版本与您在 Dockerfile 中指定的[基本映像](https://gallery.ecr.aws/lambda/dotnet)版本相符。
+ [Docker](https://docs.docker.com/get-docker)（最低版本 25.0.0）
+ Docker [buildx 插件](https://github.com/docker/buildx/blob/master/README.md)。

### 使用基本映像创建和部署映像
<a name="dotnet-image-create"></a>

在以下步骤中，您将使用 [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) 和 [Amazon.Lambda.Tools](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools) 创建 .NET 项目。然后，构建 Docker 映像，将该映像上传到 Amazon ECR，并将其部署到 Lambda 函数。

1. 安装 [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) NuGet 程序包。

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. 使用 `lambda.image.EmptyFunction` 模板创建 .NET 项目。

   ```
   dotnet new lambda.image.EmptyFunction --name MyFunction --region us-east-1
   ```

   项目文件存储在 `MyFunction/src/MyFunction` 目录中：
   + **aws-lambda-tools-defaults.json**：指定用于部署 Lambda 函数的命令行选项。
   + **Function.cs**：您的 Lambda 处理程序函数代码。这是一个 C\$1 模板，该模板包含默认 `Amazon.Lambda.Core` 库和默认 `LambdaSerializer` 属性。有关序列化要求和选项的更多信息，请参阅 [C\$1 Lambda 函数中的序列化](csharp-handler.md#csharp-handler-serializer)。您可以使用提供的代码进行测试，也可以将其替换为您自己的代码。
   + **MyFunction.csproj**：.NET [项目文件](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)，其中列出了构成您的应用程序的文件和程序集。
   + **Dockerfile**：您可以使用提供的 Dockerfile 进行测试，也可以将其替换为您自己的 Dockerfile。如果您使用自己的 Dockerfile，请确保：
     + 将 `FROM` 属性设置为[基本映像的 URI](https://gallery.ecr.aws/lambda/dotnet)。基本映像和 `MyFunction.csproj` 文件中的 `TargetFramework` 必须使用相同的 .NET 版本。例如，要使用 .NET 9：
       + Dockerfile：`FROM public.ecr.aws/lambda/dotnet:9`
       + MyFunction.csproj：`<TargetFramework>net9.0</TargetFramework>`
     + 将 `CMD` 参数设置为 Lambda 函数处理程序。这应与 `aws-lambda-tools-defaults.json` 中的 `image-command` 相符。

1. 安装 Amazon.Lambda.Tools [.NET Global Tool](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/).

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   如果已安装 Amazon.Lambda.Tools，请确保您使用的是最新版本。

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. 如果尚未安装，请将目录更改为 `MyFunction/src/MyFunction`。

   ```
   cd src/MyFunction
   ```

1. 使用 Amazon.Lambda.Tools 构建 Docker 映像，将其推送到新的 Amazon ECR 存储库，然后部署 Lambda 函数。

   对于 `--function-role`，指定函数[执行角色](lambda-intro-execution-role.md)的角色名称，而不是 Amazon 资源名称（ARN）。例如 `lambda-role`。

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   有关 Amazon.Lambda.Tools .NET Global Tool 的更多信息，请参阅 GitHub 上的[AWS适用于 .NET CLI 的扩展程序](https://github.com/aws/aws-extensions-for-dotnet-cli)存储库。

1. 调用函数。

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   如果一切成功，您将看到类似以下内容的响应：

   ```
   Payload:
   {"Lower":"testing the function","Upper":"TESTING THE FUNCTION"}
   
   Log Tail:
   INIT_REPORT Init Duration: 9999.81 ms   Phase: init     Status: timeout
   START RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed Version: $LATEST
   END RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed
   REPORT RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed  Duration: 3173.06 ms    Billed Duration: 3174 ms        Memory Size: 512 MB     Max Memory Used: 24 MB
   ```

1. 删除 Lambda 函数。

   ```
   dotnet lambda delete-function MyFunction
   ```

## 将备用基本映像与运行时系统接口客户端配合使用
<a name="csharp-image-clients"></a>

如果使用[仅限操作系统的基础映像](images-create.md#runtimes-images-provided)或者备用基础映像，则必须在映像中包括运行时系统接口客户端。运行时系统接口客户端可扩展 [运行时 API](runtimes-api.md)，用于管理 Lambda 和函数代码之间的交互。

以下示例演示如何使用非 AWS 基础映像构建 .NET 的容器映像，以及如何添加 [Amazon.Lambda.RuntimeSupport 程序包](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)，该程序包是 .NET 的 Lambda 运行时系统接口客户端。示例 Dockerfile 使用 Microsoft .NET 8 基本映像。

### 先决条件
<a name="dotnet-csharp-alt-prerequisites"></a>

要完成本节中的步骤，您必须满足以下条件：
+ [.NET SDK](https://dotnet.microsoft.com/download) – 以下步骤使用 .NET 9 基本映像。确保 .NET 版本与您在 Dockerfile 中指定的基本映像版本相符。
+ [Docker](https://docs.docker.com/get-docker)（最低版本 25.0.0）
+ Docker [buildx 插件](https://github.com/docker/buildx/blob/master/README.md)。

### 使用备用基本映像创建和部署映像
<a name="dotnet-alt-create"></a>

1. 安装 [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) NuGet 程序包。

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. 使用 `lambda.CustomRuntimeFunction` 模板创建 .NET 项目。此模板包括 [Amazon.Lambda.RuntimeSupport](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library) 程序包。

   ```
   dotnet new lambda.CustomRuntimeFunction --name MyFunction --region us-east-1
   ```

1. 导航到 `MyFunction/src/MyFunction` 目录。这是存储项目文件的位置。检查以下文件：
   + **aws-lambda-tools-defaults.json** – 此文件是您部署 Lambda 函数时指定命令行选项的位置。
   + **Function.cs** – 该代码包含一个类，其 `Main` 方法将 `Amazon.Lambda.RuntimeSupport` 库初始化为引导。`Main` 方法是函数进程的入口点。`Main` 方法将函数处理程序封装在引导可以使用的包装器中。有关更多信息，请参阅 GitHub 存储库中的[使用 Amazon.Lambda.RuntimeSupport 作为类库](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)。
   + **MyFunction.csproj** – 列出构成您应用程序的文件和程序集的 .NET [项目文件](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)。
   + **Readme.md** – 此文件包含有关示例 Lambda 函数的更多信息。

1. 打开 `aws-lambda-tools-defaults.json` 文件，然后添加以下各行：

   ```
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   ```
   + **package-type**：将部署包定义为容器映像。
   + **docker-host-build-output-dir**：设置构建过程的输出目录。  
**Example aws-lambda-tools-defaults.json**  

   ```
   {
     "Information": [
       "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
       "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
       "dotnet lambda help",
       "All the command line options for the Lambda command can be specified in this file."
     ],
     "profile": "",
     "region": "us-east-1",
     "configuration": "Release",
     "function-runtime": "provided.al2023",
     "function-memory-size": 256,
     "function-timeout": 30,
     "function-handler": "bootstrap",
     "msbuild-parameters": "--self-contained true",
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   }
   ```

1. 在 `MyFunction/src/MyFunction` 目录中创建一个 Dockerfile。以下示例 Dockerfile 使用 Microsoft .NET 基本映像而不是 [AWS 基本映像](#csharp-image-base)。
   + 将 `FROM` 属性设置为基本映像标识符。基本映像和 `MyFunction.csproj` 文件中的 `TargetFramework` 必须使用相同的 .NET 版本。
   + 使用 `COPY` 命令将函数复制到 `/var/task` 目录中。
   + 将 `ENTRYPOINT` 设置为您希望 Docker 容器在启动时运行的模块。在这种情况下，该模块是引导，它会初始化 `Amazon.Lambda.RuntimeSupport` 库。

   请注意，示例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。当您将容器映像部署到 Lambda 时，Lambda 会自动定义具有最低权限的默认 Linux 用户。这与标准 Docker 行为不同，标准 Docker 在未提供 `USER` 指令时默认为 `root` 用户。  
**Example Dockerfile**  

   ```
   # You can also pull these images from DockerHub amazon/aws-lambda-dotnet:8
   FROM mcr.microsoft.com/dotnet/runtime:9.0
   
   # Set the image's internal work directory
   WORKDIR /var/task
     
   # Copy function code to Lambda-defined environment variable
   COPY "bin/Release/net9.0/linux-x64"  .
     
   # Set the entrypoint to the bootstrap
   ENTRYPOINT ["/usr/bin/dotnet", "exec", "/var/task/bootstrap.dll"]
   ```

1. 安装 Amazon.Lambda.Tools [.NET Global Tools 扩展](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)。

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   如果已安装 Amazon.Lambda.Tools，请确保您使用的是最新版本。

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. 使用 Amazon.Lambda.Tools 构建 Docker 映像，将其推送到新的 Amazon ECR 存储库，然后部署 Lambda 函数。

   对于 `--function-role`，指定函数[执行角色](lambda-intro-execution-role.md)的角色名称，而不是 Amazon 资源名称（ARN）。例如 `lambda-role`。

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   有关 Amazon.Lambda.Tools .NET CLI 扩展程序的更多信息，请参阅 GitHub 上的[适用于 .NET CLI 的 AWS 扩展程序](https://github.com/aws/aws-extensions-for-dotnet-cli)存储库。

1. 调用函数。

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   如果所有操作成功，您将看到以下内容：

   ```
   Payload:
   "TESTING THE FUNCTION"
   
   Log Tail:
   START RequestId: id Version: $LATEST
   END RequestId: id
   REPORT RequestId: id  Duration: 0.99 ms       Billed Duration: 1 ms         Memory Size: 256 MB     Max Memory Used: 12 MB
   ```

1. 删除 Lambda 函数。

   ```
   dotnet lambda delete-function MyFunction
   ```