

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Ruby 建置 Lambda 函數
<a name="lambda-ruby"></a>

您可以在 AWS Lambda中執行 Ruby 程式碼。Lambda 提供用於執行程式碼來處理事件的 Ruby [執行期](lambda-runtimes.md)。您的程式碼會在包含 的環境中執行 適用於 Ruby 的 AWS SDK，其中包含您管理之 AWS Identity and Access Management (IAM) 角色的登入資料。若要進一步了解 Ruby 執行時期隨附的 SDK 版本，請參閱 [包含執行時期的 SDK 版本](#ruby-sdk-included)。

Lambda 支援以下 Ruby 執行期。


| 名稱 | 識別符 | 作業系統 | 取代日期 | 封鎖函數建立 | 封鎖函數更新 | 
| --- | --- | --- | --- | --- | --- | 
|  Ruby 3.4  |  `ruby3.4`  |  Amazon Linux 2023  |   2028 年 3 月 31 日   |   2028 年 4 月 30 日   |   2028 年 5 月 31 日   | 
|  Ruby 3.3  |  `ruby3.3`  |  Amazon Linux 2023  |   2027 年 3 月 31 日   |   2027 年 4 月 30 日   |   2027 年 5 月 31 日   | 
|  Ruby 3.2  |  `ruby3.2`  |  Amazon Linux 2  |   2026 年 3 月 31 日   |   2026 年 8 月 31 日   |   2026 年 9 月 30 日   | 

**建立 Ruby 函式**

1. 開啟 [Lambda 主控台](https://console.aws.amazon.com/lambda)。

1. 選擇**建立函數**。

1. 進行下列設定：
   + **函數名稱**：輸入函數名稱。
   + **執行時間**：選擇 **Ruby 3.4。**

1. 選擇**建立函數**。

主控台將建立一個 Lambda 函數，其具有名為 `lambda_function.rb` 的單一來源檔案。您可以使用內建的程式碼編輯器編輯該檔案並加入更多檔案。在 **DEPLOY** 區段中，選擇**部署**以更新函數的程式碼。然後，若要執行程式碼，請在**測試事件**區段中選擇**建立測試事件**。

`lambda_function.rb` 檔案匯出名為 `lambda_handler` 的函數，它接受事件物件與內容物件。這就是在調用函數時，Lambda 呼叫的[處理常式函數](ruby-handler.md)。Ruby 函數執行期會從 Lambda 中取得調用事件並其傳遞至處理常式。在函式組態中，處理常式值為 `lambda_function.lambda_handler`。

當您儲存函數程式碼時，Lambda 主控台會建立 .zip 封存檔部署套件。當您在主控台之外開發函數程式碼 (使用 IDE) 時，您需要[建立部署套件](ruby-package.md)將您的程式碼上傳到 Lambda 函數。

除了傳遞調用事件外，函式執行期還會傳遞內容物件至處理常式。[內容物件](ruby-context.md)包含了有關調用、函式以及執行環境的額外資訊。更多詳細資訊將另由環境變數提供。

Lambda 函數隨附有 CloudWatch Logs 記錄群組。函數執行期會將每次調用的詳細資訊傳送至 CloudWatch Logs。它在調用期間會轉送[您的函數輸出的任何記錄](ruby-logging.md)。如果您的函數傳回錯誤，Lambda 會對該錯誤進行格式化之後傳回給調用端。

**Topics**
+ [

## 包含執行時期的 SDK 版本
](#ruby-sdk-included)
+ [

## 啟用 Yet Another Ruby JIT (YJIT)
](#ruby-yjit)
+ [

# 以 Ruby 定義 Lambda 函數處理常式
](ruby-handler.md)
+ [

# 使用 .zip 封存檔部署 Ruby Lambda 函數
](ruby-package.md)
+ [

# 使用容器映像部署 Ruby Lambda 函數
](ruby-image.md)
+ [

# 針對 Ruby Lambda 函數使用層
](ruby-layers.md)
+ [

# 使用 Lambda 內容物件擷取 Ruby 函數資訊
](ruby-context.md)
+ [

# 記錄和監控 Ruby Lambda 函數
](ruby-logging.md)
+ [

# 在 中檢測 Ruby 程式碼 AWS Lambda
](ruby-tracing.md)

## 包含執行時期的 SDK 版本
<a name="ruby-sdk-included"></a>

Ruby 執行時間中包含的 AWS SDK 版本取決於執行時間版本和您的 AWS 區域。適用於 Ruby 的 AWS SDK 設計為模組化，並以 分隔 AWS 服務。若要尋找您使用之執行時期中包含的特定服務 Gem 的版本編號，請使用下列格式的程式碼建立 Lambda 函數。將 `aws-sdk-s3` 和 `Aws::S3` 取代為程式碼使用的服務 Gem 名稱。

```
require 'aws-sdk-s3'

def lambda_handler(event:, context:)
  puts "Service gem version: #{Aws::S3::GEM_VERSION}"
  puts "Core version: #{Aws::CORE_GEM_VERSION}"
end
```

## 啟用 Yet Another Ruby JIT (YJIT)
<a name="ruby-yjit"></a>

Ruby 執行時間支援 [YJIT](https://docs.ruby-lang.org/en/master/jit/yjit_md.html)，這是一種輕量、極簡的 Ruby JIT 編譯器。YJIT 提供了明顯更高的性能，但使用的記憶體也比 Ruby 解譯器更多。建議將 YJIT 用於 Ruby on Rails 工作負載。

依預設不會啟用 YJIT。若要為 Ruby 函數啟用 YJIT，請將`RUBY_YJIT_ENABLE`環境變數設定為 `1`。若要確認已啟用 YJIT，請列印 `RubyVM::YJIT.enabled?` 方法的結果。

**Example – 確認已啟用 YJIT**  

```
puts(RubyVM::YJIT.enabled?())
# => true
```

# 以 Ruby 定義 Lambda 函數處理常式
<a name="ruby-handler"></a>

Lambda 函數*處理常式*是您的函數程式碼中處理事件的方法。當有人呼叫您的函數時，Lambda 會執行處理常式方法。函數會執行，直到處理常式傳回回應、結束或逾時為止。

**Topics**
+ [

## Ruby 處理常式基本概念
](#ruby-handler-basics)
+ [

## Ruby Lambda 函數的程式碼最佳實務
](#ruby-best-practices)

## Ruby 處理常式基本概念
<a name="ruby-handler-basics"></a>

以下範例中，檔案 `function.rb` 定義了一個名為 `handler` 的處理常式方法。此處理常式函式接受兩個物件做為輸入並將傳回 JSON 文件。

**Example function.rb**  

```
require 'json'

def handler(event:, context:)
    { event: JSON.generate(event), context: JSON.generate(context.inspect) }
end
```

在您的函數組態中，`handler` 設定會告知 Lambda 應至何處尋找處理常式。接續前述範例，此設定的正確值為 **function.handler**。其包括兩個以句點分隔的名稱：檔案的名稱和處理常式方法的名稱。

您也可以透過類別定義處理常式方法。以下範例在名為 `process` 的模組之下透過名為 `Handler` 的類別定義 `LambdaFunctions` 處理常式方法。

**Example source.rb**  

```
module LambdaFunctions
  class Handler
    def self.process(event:,context:)
      "Hello!"
    end
  end
end
```

就本例而言，handler 設定是 **source.LambdaFunctions::Handler.process**。

處理常式接受的兩個物件分別為叫用事件和內容。事件是 Ruby 物件，其包含了由叫用端所提供的承載。如果承載是 JSON 文件，事件物件即為 Ruby 雜湊；否則將會是字串。[內容物件](ruby-context.md)具有方法和各項屬性，提供了有關叫用、函式以及執行環境的資訊。

每次叫用您的 Lambda 函數時都將執行函數處理常式。位於處理常式外部的靜態程式碼則是按照函式的每一執行個體各執行一次。如果您的處理常式使用了像是開發套件用戶端和資料庫連線之類的資源，您即可由處理常式方法外部建立該等資源，以供多次叫用時重複使用。

函式的每一執行個體均可處理多個叫用事件，但是一次僅處理一個事件。在任何特定時間內處理某一事件的執行個體數目稱為函式的*並行數*。如需 Lambda 執行環境的詳細資訊，請參閱 [了解 Lambda 執行環境生命週期](lambda-runtime-environment.md)。

## Ruby Lambda 函數的程式碼最佳實務
<a name="ruby-best-practices"></a>

請遵循下列清單中的準則，在建置 Lambda 函數時使用最佳編碼實務：
+ **區隔 Lambda 處理常式與您的核心邏輯。**能允許您製作更多可測單位的函式。例如，在 Ruby 中，這可能看起來像是：

  ```
  def lambda_handler(event:, context:)
      foo = event['foo']
      bar = event['bar']
      
      result = my_lambda_function(foo:, bar:)
  
  end
  
  def my_lambda_function(foo:, bar:)
      // MyLambdaFunction logic here
      
  end
  ```
+ **控制函數部署套件內的相依性。**AWS Lambda 執行環境包含多個程式庫。對於 Ruby 執行時期，其中包含 AWS SDK。若要啟用最新的一組功能與安全更新，Lambda 會定期更新這些程式庫。這些更新可能會為您的 Lambda 函數行為帶來細微的變更。若要完全掌控您函式所使用的相依性，請利用部署套件封裝您的所有相依性。
+ **最小化依存項目的複雜性。**偏好更簡易的框架，其可快速在[執行環境](lambda-runtime-environment.md)啟動時載入。
+ **將部署套件最小化至執行時期所必要的套件大小。**這能減少您的部署套件被下載與呼叫前解壓縮的時間。對於以 Ruby 撰寫的函數，請避免上傳整個 AWS SDK 程式庫做為部署套件的一部分。或者，選擇性倚賴取得您需要的 SDK 元件的 Gem 套件 (例如 DynamoDB 或 Amazon S3 Gem 套件)。

**請利用執行環境重新使用來改看函式的效能。**在函式處理常式之外初始化 SDK 用戶端和資料庫連線，並在本機快取 `/tmp` 目錄中的靜態資產。由您函式的相同執行個體處理的後續叫用可以重複使用這些資源。這可藉由減少函數執行時間來節省成本。

若要避免叫用間洩漏潛在資料，請不要使用執行環境來儲存使用者資料、事件，或其他牽涉安全性的資訊。如果您的函式依賴無法存放在處理常式內記憶體中的可變狀態，請考慮為每個使用者建立個別函式或個別函式版本。

**使用 Keep-Alive 指令維持持續連線的狀態。**Lambda 會隨著時間的推移清除閒置連線。叫用函數時嘗試重複使用閒置連線將導致連線錯誤。若要維護持續連線，請使用與執行階段相關聯的 keep-alive (保持啟用) 指令。如需範例，請參閱[在 Node.js 中重複使用 Keep-Alive 的連線](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)。

**使用[環境變數](configuration-envvars.md)將操作參數傳遞給您的函數。**例如，如果您正在寫入到 Amazon S3 儲存貯體，而非對您正在寫入的儲存貯體名稱進行硬式編碼，請將儲存貯體名稱設定為環境變數。

**避免在 Lambda 函數中使用遞迴調用**，其中函數會調用自己或啟動可能再次調用函數的程序。這會導致意外的函式呼叫量與升高的成本。若您看到意外的調用數量，當更新程式碼時，請立刻將函數的預留並行設為 `0`，以調節對函數的所有調用。

**請勿在您的 Lambda 函數程式碼中使用未記錄的非公有 API**。對於 AWS Lambda 受管執行時間，Lambda 會定期將安全性和函數更新套用至 Lambda 的內部 API。這些內部 API 更新可能是向後不相容的，這會導致意外結果，例如若您的函數依賴於這些非公有 API，則叫用失敗。請參閱 [API 參考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)查看公開可用 API 的清單。

**撰寫等冪程式碼。**為函數撰寫等冪程式碼可確保採用相同方式來處理重複事件。程式碼應正確驗證事件並正常處理重複的事件。如需詳細資訊，請參閱 [How do I make my Lambda function idempotent?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/) (如何讓 Lambda 函數等冪？)。

# 使用 .zip 封存檔部署 Ruby Lambda 函數
<a name="ruby-package"></a>

 AWS Lambda 函數的程式碼包含一個 .rb 檔案 (內含函數的處理常式程式碼)，以及您的程式碼所依賴的任何其他相依項 (Gem)。若要將此函數程式碼部署到 Lambda，您可以使用*部署套件*。此套件可以是 .zip 封存檔或容器映像。如需搭配 Ruby 使用容器映像的詳細資訊，請參閱[使用容器映像部署 Ruby Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/ruby-image.html)。

 若要建立 .zip 封存檔的部署套件，您可以使用命令列工具的內建 .zip 封存檔公用程式，或任何其他 .zip 檔案公用程式 (例如 [7zip](https://www.7-zip.org/download.html))。以下各節顯示的範例假設您在 Linux 或 MacOS 環境中使用命令列 `zip` 工具。若要在 Windows 中使用相同命令，您可以[安裝適用於 Linux 的 Windows 子系統](https://docs.microsoft.com/en-us/windows/wsl/install-win10)，以取得 Ubuntu 和 Bash 的 Windows 整合版本。

 請注意，Lambda 使用 POSIX 檔案許可，因此在建立 .zip 封存檔之前，您可能需要[設定部署套件資料夾的許可](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-deployment-package-errors/)。

以下各節中的範例命令使用 [Bundler](https://bundler.io/) 公用程式，將相依項新增至部署套件。若要安裝 bundler，請執行下列命令。

```
gem install bundler
```

**Topics**
+ [

## Ruby 中的相依項
](#ruby-package-runtime-dependencies)
+ [

## 建立不含相依項的 .zip 部署套件
](#ruby-package-codeonly)
+ [

## 建立含相依項的 .zip 部署套件
](#ruby-package-dependencies)
+ [

## 為相依項建立 Ruby 層
](#ruby-package-dependencies-layers)
+ [

## 建立含原生程式庫的 .zip 部署套件
](#ruby-package-native)
+ [

## 使用 .zip 檔案建立及更新 Ruby Lambda 函數
](#ruby-package-create-functions)

## Ruby 中的相依項
<a name="ruby-package-runtime-dependencies"></a>

對於使用 Ruby 執行期的 Lambda 函數，相依項可以是任何 Ruby gem。使用 .zip 封存部署函數時，您可以使用函數程式碼將這些相依項新增至 .zip 檔案，或使用 Lambda 層。 圖層是單獨的 .zip 檔案，可以包含其他程式碼和內容。若要進一步了解如何使用 Lambda 層，請參閱 [使用層管理 Lambda 相依項](chapter-layers.md)。

Ruby 執行時期包括 適用於 Ruby 的 AWS SDK。如果函數使用 SDK，則不需要將其與程式碼綁定在一起。但是，若要維持相依項的完全控制或使用特定版本的 SDK，可以將其新增到函數的部署套件。您可以將 SDK 包含在 .zip 檔案中，也可以使用 Lambda 層進行新增。.zip 檔案或 Lambda 層中的相依項優先於執行期中包含的版本。若要查看適用於 Ruby 的哪個 SDK 版本包含在執行時期版本中，請參閱[包含執行時期的 SDK 版本](lambda-ruby.md#ruby-sdk-included)。

 在 [AWS 共同責任模式](lambda-runtimes.md#runtimes-shared-responsibility)下，您負責管理函數部署套件中的任何相依項。這包括套用更新和安全性修補程式。若要更新函數部署套件中的相依項，請先建立新的 .zip 檔案，然後將其上傳至 Lambda。如需詳細資訊，請參閱 [建立含相依項的 .zip 部署套件](#ruby-package-dependencies) 和 [使用 .zip 檔案建立及更新 Ruby Lambda 函數](#ruby-package-create-functions)。

## 建立不含相依項的 .zip 部署套件
<a name="ruby-package-codeonly"></a>

如果您的函數程式碼沒有相依項，則 .zip 檔案只會包含具有函數處理常式程式碼的 .rb 檔案。使用您慣用的 zip 公用程式建立 .zip 檔案，並將 .rb 檔案放在根目錄下。如果 .rb 檔案不在 .zip 檔案的根目錄下，則 Lambda 將無法執行您的程式碼。

若要了解如何部署 .zip 檔案以建立新的 Lambda 函數或更新現有函數，請參閱[使用 .zip 檔案建立及更新 Ruby Lambda 函數](#ruby-package-create-functions)。

## 建立含相依項的 .zip 部署套件
<a name="ruby-package-dependencies"></a>

如果您的函數程式碼相依於其他 Ruby gem，則您可以使用函數程式碼將這些相依項新增至 .zip 檔案，或使用 [Lambda 層](chapter-layers.md)。本節中的指示說明如何在 .zip 部署套件中包含相依項。如需如何在層中包含相依項的指示，請參閱[為相依項建立 Ruby 層](#ruby-package-dependencies-layers)。

假設函數程式碼儲存在專案目錄中名為 `lambda_function.rb` 的檔案中。下列範例 CLI 命令會建立名為 `my_deployment_package.zip` 的 .zip 檔案，其中包含函數程式碼及其相依項。

**建立部署套件**

1. 在專案目錄中，建立 `Gemfile` 以在其中指定相依項。

   ```
   bundle init
   ```

1. 使用您偏好的文字編輯器，編輯 `Gemfile` 以指定函數的相依項。例如，若要使用 TZInfo gem，請編輯 `Gemfile`，如下所示。

   ```
   source "https://rubygems.org"
   gem "tzinfo"
   ```

1. 執行以下命令來安裝專案目錄中 `Gemfile` 指定的 gem。此命令將 `vendor/bundle` 設定為 gem 安裝的預設路徑。

   ```
   bundle config set --local path 'vendor/bundle' && bundle install
   ```

   您應該會看到類似下列的輸出。

   ```
   Fetching gem metadata from https://rubygems.org/...........
   Resolving dependencies...
   Using bundler 2.4.13
   Fetching tzinfo 2.0.6
   Installing tzinfo 2.0.6
   ...
   ```
**注意**  
若稍後再次在全域安裝 gem，請執行下列命令。  

   ```
   bundle config set --local system 'true'
   ```

1. 建立 .zip 封存檔，其中包含具有函數處理常式程式碼的 `lambda_function.rb` 檔案以及在上一個步驟中安裝的相依項。

   ```
   zip -r my_deployment_package.zip lambda_function.rb vendor
   ```

   您應該會看到類似下列的輸出。

   ```
   adding: lambda_function.rb (deflated 37%)
     adding: vendor/ (stored 0%)
     adding: vendor/bundle/ (stored 0%)
     adding: vendor/bundle/ruby/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/build_info/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/cache/ (stored 0%)
     adding: vendor/bundle/ruby/3.2.0/cache/aws-eventstream-1.0.1.gem (deflated 36%)
   ...
   ```

## 為相依項建立 Ruby 層
<a name="ruby-package-dependencies-layers"></a>

若要了解如何將 Ruby 相依項封裝至 Lambda 層中，請參閱[針對 Ruby Lambda 函數使用層](ruby-layers.md)。

## 建立含原生程式庫的 .zip 部署套件
<a name="ruby-package-native"></a>

諸如 `nokogiri`、`nio4r` 和 `mysql` 等許多常見 Ruby gem 包含用 C 語言編寫的原生延伸模組。將包含 C 程式碼的程式庫新增至部署套件時，必須正確建置套件，以確保其與 Lambda 執行環境相容。

對於生產應用程式，建議您使用 AWS Serverless Application Model (AWS SAM) 來建置和部署程式碼。在 AWS SAM 中，使用 `sam build --use-container` 選項在類似 Lambda 的 Docker 容器中建置函數。若要進一步了解如何使用 AWS SAM 來部署函數程式碼，請參閱《AWS SAM 開發人員指南》**中的[建置應用程式](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-using-build.html)。

若要在不使用 AWS SAM 的情況下建立包含 gem (帶有原生延伸模組) 的 .zip 部署套件，您也可以使用容器將相依項綁定在與 Lambda Ruby 執行期環境相同的環境中。若要完成這些步驟，必須在建置電腦上安裝 Docker。若要進一步了解如何安裝 Docker，請參閱 [Install Docker Engine](https://docs.docker.com/engine/install/)。

**在 Docker 容器中建立 .zip 部署套件**

1. 在本機建置電腦上建立一個資料夾，將容器儲存在其中。在該資料夾中，建立一個名為 `dockerfile` 的檔案並將以下程式碼貼到其中。

   ```
   FROM public.ecr.aws/sam/build-ruby3.2:latest-x86_64
   RUN gem update bundler 
   CMD "/bin/bash"
   ```

1. 在建立 `dockerfile` 的資料夾中，執行以下命令以建立 Docker 容器。

   ```
   docker build -t awsruby32 .
   ```

1. 導覽到包含 `.rb` 檔案 (具有函數處理常式程式碼) 和 `Gemfile` (用於指定函數相依項) 的專案目錄。從該目錄內，執行下列命令以啟動 Lambda Ruby 容器。

------
#### [ Linux/MacOS ]

   ```
   docker run --rm -it -v $PWD:/var/task -w /var/task awsruby32
   ```

**注意**  
在 MacOS 中，您可能會看到警告，通知您所請求映像的平台與偵測到的主機平台不符。請忽略此警告。

------
#### [ Windows PowerShell ]

   ```
   docker run --rm -it -v ${pwd}:var/task -w /var/task awsruby32
   ```

------

   當容器啟動時，應能看到一個 bash 提示。

   ```
   bash-4.2#
   ```

1. 設定套件公用程式，以安裝本機 `vendor/bundle` 目錄中 `Gemfile` 指定的 gem，並安裝相依項。

   ```
   bash-4.2# bundle config set --local path 'vendor/bundle' && bundle install
   ```

1. 使用函數程式碼和其相依項建立 .zip 部署套件。在此範例中，包含函數處理常式程式碼的檔案命名為 `lambda_function.rb`。

   ```
   bash-4.2# zip -r my_deployment_package.zip lambda_function.rb vendor
   ```

1. 結束容器並回到本機專案目錄。

   ```
   bash-4.2# exit
   ```

   現在可以使用 .zip 檔案部署套件來建立或更新 Lambda 函數。請參閱 [使用 .zip 檔案建立及更新 Ruby Lambda 函數](#ruby-package-create-functions)

## 使用 .zip 檔案建立及更新 Ruby Lambda 函數
<a name="ruby-package-create-functions"></a>

 建立 .zip 部署套件後，您可以使用該套件建立新的 Lambda 函數或更新現有函數。您可以使用 Lambda 主控台、AWS Command Line Interface 及 Lambda API 部署 .zip 套件。您也可以使用 AWS Serverless Application Model (AWS SAM) 和 CloudFormation 建立並更新 Lambda 函數。

Lambda 的 .zip 部署套件大小上限為 250 MB (解壓縮)。請注意，此限制適用於您上傳的所有檔案 (包括任何 Lambda 層) 的大小總和。

Lambda 執行時間需有許可才能讀取部署套裝服務中的檔案。在 Linux 許可八進位標記法中，Lambda 需要 644 個許可 (rw-r--r--) 用於非可執行檔，以及 755 個許可 (rwxr-x) 用於目錄和可執行檔。

在 Linux 和 MacOS 中，使用 `chmod` 命令變更部署套件中檔案和目錄的檔案許可。例如，若要為非可執行檔提供正確的許可，請執行下列命令。

```
chmod 644 <filepath>
```

若要在 Windows 中變更檔案許可，請參閱 Microsoft Windows 文件的 [Set, View, Change, or Remove Permissions on an Object](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc731667(v=ws.10))。

**注意**  
如果您未授予 Lambda 存取部署套件中的目錄所需的許可，Lambda 會將這些目錄的許可設定為 755 (rwxr-xr-x)。

### 透過主控台使用 .zip 檔案建立及更新函數
<a name="ruby-package-create-console"></a>

 若要建立新函數，您必須先在主控台中建立函數，然後上傳您的 .zip 封存檔。若要更新現有函數，請開啟函數的頁面，然後按照同樣的程序新增更新後的 .zip 檔案。

 如果您的 .zip 檔案小於 50 MB，您可以透過直接從本機電腦上傳檔案來建立或更新函數。若 .zip 檔案大於 50 MB，您必須先將套件上傳至 Amazon S3 儲存貯體。如需透過 AWS 管理主控台 將檔案上傳至 Amazon S3 儲存貯體的指示，請參閱[《Amazon S3 入門》](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html)。若要使用 AWS CLI 上傳檔案，請參閱*AWS CLI《使用者指南》* 中的[移動物件](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

**注意**  
不能變更現有函數的[部署套件類型](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-PackageType) (.zip 或容器映像)。例如，您不能轉換容器映像函數以使用 .zip 封存檔。您必須建立新的函數。

**若要建立新的函數 (主控台)**

1. 開啟 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)，然後選擇**建立函數**。

1. 選擇 **Author from scratch** (從頭開始撰寫)。

1. 在**基本資訊**下，請執行下列動作：

   1. 在**函數名稱**中輸入函數名稱。

   1. 在**執行期**中選取要使用的執行期。

   1. (選用) 在**架構**中選擇要用於函數的指令集架構。預設架構值為 x86\$164。請確定函數的 .zip 部署套件與您選取的指令集架構相容。

1. (選用) 在**許可**下，展開**變更預設執行角色**。您可建立新的**執行角色**，或使用現有的角色。

1. 選擇 **Create function (建立函數)**。Lambda 會使用您選擇的執行期建立一個基本的「Hello world」函數。

**若要從本機電腦上傳 .zip 封存檔 (主控台)**

1. 在 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)中選擇要上傳 .zip 檔案的函數。

1. 選取**程式碼**索引標籤。

1. 在**程式碼來源**窗格中選擇**上傳來源**。

1. 選擇 **.zip 檔案**。

1. 若要上傳 .zip 檔案，請執行下列操作：

   1. 選擇**上傳**，然後在檔案選擇器中選取您的 .zip 檔案。

   1. 選擇 **Open (開啟)**。

   1. 選擇**儲存**。

**若要從 Amazon S3 儲存貯體上傳 .zip 封存檔 (控制台)**

1. 在 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)中選擇要上傳新 .zip 檔案的函數。

1. 選取**程式碼**索引標籤。

1. 在**程式碼來源**窗格中選擇**上傳來源**。

1. 選擇 **Amazon S3 位置**。

1. 貼上 .zip 檔案的 Amazon S3 連結 URL，然後選擇**儲存**。

### 使用主控台程式碼編輯器更新 .zip 檔案函數
<a name="ruby-package-console-edit"></a>

 對於某些具有 .zip 部署套件的函數，您可以使用 Lambda 主控台的內建程式碼編輯器直接更新函數程式碼。若要使用此功能，您的函數必須符合下列條件：
+ 您的函數必須使用其中一種轉譯語言執行期 (Python、Node.js 或 Ruby)
+ 函數的部署套件必須小於 50 MB (未壓縮)。

具有容器映像部署套件之函數的函數程式碼無法直接在主控台中編輯。

**若要使用主控台程式碼編輯器更新函數程式碼**

1. 開啟 Lambda 主控台的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)，然後選取您的函數。

1. 選取**程式碼**索引標籤。

1. 在**程式碼來源**窗格中，選取您的原始程式碼檔案，然後在整合式程式碼編輯器中加以編輯。

1. 在 **DEPLOY** 區段中，選擇**部署**以更新函數的程式碼：  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

### 透過 AWS CLI 使用 .zip 檔案建立及更新函數
<a name="ruby-package-create-cli"></a>

 您可以使用 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 建立新函數，或使用 .zip 檔案更新現有函數。使用 [create-function](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) 和 [update-function-code](https://docs.aws.amazon.com/cli/latest/reference/lambda/create-function.html) 命令來部署您的 .zip 套件。如果您的 .zip 檔案小於 50 MB，則可以從本機建置電腦的檔案位置上傳 .zip 套件。若檔案較大，則必須先從 Amazon S3 儲存貯體上傳 .zip 套件。如需透過 AWS CLI 將檔案上傳至 Amazon S3 儲存貯體的指示，請參閱*《AWS CLI 使用者指南》*中的 [移動物件](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

**注意**  
如果您透過 AWS CLI 從 Amazon S3 儲存貯體上傳 .zip 檔案，則儲存貯體必須與函數位於相同的 AWS 區域。

 若要使用 .zip 檔案與 AWS CLI 建立新函數，您必須指定下列項目：
+ 函數名稱 (`--function-name`)
+ 函數的執行期 (`--runtime`)
+ 函數[執行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)的 Amazon Resource Name (ARN) (`--role`)
+ 函數程式碼中處理常式方法的名稱 (`--handler`)

 您也必須指定 .zip 檔案的位置。如果您的 .zip 檔案位於本機建置電腦上的資料夾中，請使用 `--zip-file` 選項來指定檔案路徑，如下列範例命令所示。

```
aws lambda create-function --function-name myFunction \
--runtime ruby3.2 --handler lambda_function.lambda_handler \
--role arn:aws:iam::111122223333:role/service-role/my-lambda-role \
--zip-file fileb://myFunction.zip
```

 若要在 Amazon S3 儲存貯體中指定 .zip 檔案的位置，請使用如下列範例命令所示的 `--code` 選項。您只需針對版本控制的物件使用 `S3ObjectVersion` 參數。

```
aws lambda create-function --function-name myFunction \
--runtime ruby3.2 --handler lambda_function.lambda_handler \
--role arn:aws:iam::111122223333:role/service-role/my-lambda-role \
--code S3Bucket=amzn-s3-demo-bucket,S3Key=myFileName.zip,S3ObjectVersion=myObjectVersion
```

 若要使用 CLI 更新現有函數，您可以使用 `--function-name` 參數指定函數的名稱。您也必須指定要用來更新函數程式碼的 .zip 檔案的位置。如果您的 .zip 檔案位於本機建置電腦上的資料夾中，請使用 `--zip-file` 選項來指定檔案路徑，如下列範例命令所示。

```
aws lambda update-function-code --function-name myFunction \
--zip-file fileb://myFunction.zip
```

 若要在 Amazon S3 儲存貯體中指定 .zip 檔案的位置，請使用如下列範例命令所示的 `--s3-bucket` 和 `--s3-key` 選項。您只需針對版本控制的物件使用 `--s3-object-version` 參數。

```
aws lambda update-function-code --function-name myFunction \
--s3-bucket amzn-s3-demo-bucket --s3-key myFileName.zip --s3-object-version myObject Version
```

### 透過 Lambda API 使用 .zip 檔案建立及更新函數
<a name="ruby-package-create-api"></a>

 若要使用 .zip 封存檔建立及更新函數，請使用下列 API 操作：
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)
+ [UpdateFunctionCode](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionCode.html)

### 透過 AWS SAM 使用 .zip 檔案建立及更新函數
<a name="ruby-package-create-sam"></a>

 AWS Serverless Application Model(AWS SAM) 是一項工具組，可協助簡化在 AWS 上建置和執行無伺服器應用程式的程序。您可以在 YAML 或 JSON 範本中定義應用程式的資源，並使用 AWS SAM 命令列界面 (AWS SAM CLI) 來建置、封裝及部署應用程式。使用 AWS SAM 範本建置 Lambda 函數時，AWS SAM 會使用函數程式碼和您指定的任何相依項目自動建立 .zip 部署套件或容器映像。若要進一步了解如何使用 AWS SAM 建置和部署 Lambda 函數，請參閱*《AWS Serverless Application Model 開發人員指南》*中的 [AWS SAM入門](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)。

您也可以使用 AWS SAM 來建立使用現有 .zip 封存檔的 Lambda 函數。若要使用 AWS SAM 建立 Lambda 函數，您可以將 .zip 檔案儲存在 Amazon S3 儲存貯體或建置電腦的本機資料夾中。如需透過 AWS CLI 將檔案上傳至 Amazon S3 儲存貯體的指示，請參閱*《AWS CLI 使用者指南》*中的 [移動物件](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

 在您的 AWS SAM 範本中，`AWS::Serverless::Function` 資源會指定您的 Lambda 函數。在本資源中設定下列屬性，以使用 .zip 封存檔建立函數：
+ `PackageType`：設定為 `Zip`
+ `CodeUri`：設定為函數程式碼的 Amazon S3 URI、本機資料夾的路徑或 [FunctionCode](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-functioncode.html) 物件
+ `Runtime`：設定為所選執行期

 在使用 AWS SAM 的情況下，如果您的 .zip 檔案大於 50 MB，則不需要先將檔案上傳至 Amazon S3 儲存貯體。AWS SAM 可以從本機建置電腦上的位置上傳大小上限為 250 MB (解壓縮) 的 .zip 套件。

 若要進一步了解如何在 AWS SAM 中使用 .zip 檔案部署函數，請參閱*《AWS SAM 開發人員指南》*中的 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)。

### 透過 CloudFormation 使用 .zip 檔案建立及更新函數
<a name="ruby-package-create-cfn"></a>

 您可以使用 CloudFormation 來建立使用 .zip 封存檔的 Lambda 函數。若要使用 .zip 檔案建立 Lambda 函數，您必須先將檔案上傳至 Amazon S3 儲存貯體。如需透過 AWS CLI 將檔案上傳至 Amazon S3 儲存貯體的指示，請參閱*《AWS CLI 使用者指南》*中的 [移動物件](https://docs.aws.amazon.com/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-move)。

在您的 CloudFormation 範本中，`AWS::Lambda::Function` 資源會指定您的 Lambda 函數。在本資源中設定下列屬性，以使用 .zip 封存檔建立函數：
+ `PackageType`：設定為 `Zip`
+ `Code`：在 `S3Bucket` 和 `S3Key` 欄位中輸入 Amazon S3 儲存貯體名稱和 .zip 檔案名稱。
+ `Runtime`：設定為所選執行期

 CloudFormation 產生的 .zip 檔案不能超過 4 MB。若要進一步了解如何在 CloudFormation 中使用 .zip 檔案部署函數，請參閱*《CloudFormation 使用者指南》*中的 [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)。

# 使用容器映像部署 Ruby Lambda 函數
<a name="ruby-image"></a>

有三種方法可以為 Ruby Lambda 函數構建容器映像：
+ [使用 Ruby AWS 的基礎映像](#ruby-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 相容，您必須在映像中加入[適用於 Ruby 的執行期介面用戶端](#ruby-image-clients)。
+ [使用非AWS 基礎映像](#ruby-image-clients)

  您可以使用其他容器登錄檔中的替代基礎映像 (例如 Alpine Linux 或 Debian)。您也可以使用組織建立的自訂映像。若要使映像與 Lambda 相容，您必須在映像中加入[適用於 Ruby 的執行期介面用戶端](#ruby-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 Ruby 的基礎映像
](#ruby-image-base)
+ [

## 使用 Ruby AWS 的基礎映像
](#ruby-image-instructions)
+ [

## 透過執行期介面用戶端使用替代基礎映像
](#ruby-image-clients)

## AWS Ruby 的基礎映像
<a name="ruby-image-base"></a>

AWS 為 Ruby 提供下列基礎映像：


| Tags (標籤) | 執行期 | 作業系統 | Dockerfile | 棄用 | 
| --- | --- | --- | --- | --- | 
| 3.4 | Ruby 3.4 | Amazon Linux 2023 | [GitHub 上適用於 Ruby 3.4 的 Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/ruby3.4/Dockerfile.ruby3.4) |   2028 年 3 月 31 日   | 
| 3.3 | Ruby 3.3 | Amazon Linux 2023 | [Dockerfile for Ruby 3.3 on GitHub](https://github.com/aws/aws-lambda-base-images/blob/ruby3.3/Dockerfile.ruby3.3) |   2027 年 3 月 31 日   | 
| 3.2 | Ruby 3.2 | Amazon Linux 2 | [Dockerfile for Ruby 3.2 on GitHub](https://github.com/aws/aws-lambda-base-images/blob/ruby3.2/Dockerfile.ruby3.2) |   2026 年 3 月 31 日   | 

Amazon ECR 儲存庫：[gallery.ecr.aws/lambda/ruby](https://gallery.ecr.aws/lambda/ruby)

## 使用 Ruby AWS 的基礎映像
<a name="ruby-image-instructions"></a>

### 先決條件
<a name="ruby-image-prerequisites"></a>

若要完成本節中的步驟，您必須執行下列各項：
+ [AWS CLI 第 2 版](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (最低版本 25.0.0)
+ Docker [buildx 外掛程式](https://github.com/docker/buildx/blob/master/README.md)。
+ Ruby

### 從基礎映像建立映像
<a name="ruby-image-create"></a>

**建立適用於 Ruby 的容器映像**

1. 建立專案的目錄，然後切換至該目錄。

   ```
   mkdir example
   cd example
   ```

1. 建立稱為 `Gemfile` 的新檔案。應用程式所需的 RubyGems 套件須列在這裡。可從 RubyGems 適用於 Ruby 的 AWS SDK 取得。您應該選擇要安裝的特定 AWS 服務 Gem 套件。例如，若要使用 [Ruby Gem for Lambda](https://rubygems.org/gems/aws-sdk-lambda/)，您的 Gemfile 看起來應該會像：

   ```
   source 'https://rubygems.org'
   
   gem 'aws-sdk-lambda'
   ```

   或者，[aws-sdk](https://rubygems.org/gems/aws-sdk/) Gem 套件包含每個可用的 AWS 服務 Gem。這個 Gem 非常大，建議您只在依賴許多 AWS 服務時才使用它。

1. 使用[套件安裝作業](https://bundler.io/v2.4/man/bundle-install.1.html)安裝 Gemfile 中指定的相依項。

   ```
   bundle install
   ```

1. 建立稱為 `lambda_function.rb` 的新檔案。您可以將下列範例函數程式碼新增至檔案進行測試，或使用您自己的函數程式碼。  
**Example Ruby 函數**  

   ```
   module LambdaFunction
     class Handler
       def self.process(event:,context:)
         "Hello from Lambda!"
       end
     end
   end
   ```

1. 建立新的 Dockerfile。下列範例 Dockerfile 使用 [AWS 基礎映像](images-create.md#runtimes-images-lp)。此 Dockerfile 使用下列組態：
   + 將 `FROM` 屬性設定為基礎映像的 URI。
   + 使用 COPY 命令將函數程式碼和執行時期相依項複製到 `{LAMBDA_TASK_ROOT}`，一個 [Lambda 定義的環境變數](configuration-envvars.md#configuration-envvars-runtime)。
   + 將 `CMD` 引數設定為 Lambda 函數處理常式。

   請注意，範例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。當您將容器映像部署到 Lambda 時，Lambda 會自動定義一個具有最低權限許可的預設 Linux 使用者。這與標準 Docker 行為不同，後者會在未提供 `USER` 指令時預設為 `root` 使用者。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/ruby:3.4
   
   # Copy Gemfile and Gemfile.lock
   COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/
   
   # Install Bundler and the specified gems
   RUN gem install bundler:2.4.20 && \
       bundle config set --local path 'vendor/bundle' && \
       bundle install
   
   # Copy function code
   COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/    
   
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "lambda_function.LambdaFunction::Handler.process" ]
   ```

1. 使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令建立 Docker 映像檔。以下範例將映像命名為 `docker-image` 並為其提供 `test` [標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。若要使映像與 Lambda 相容，必須使用 `--provenance=false` 選項。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注意**  
此命令會指定 `--platform linux/amd64` 選項，確保無論建置機器的架構為何，您的容器都與 Lambda 執行環境相容。如果您打算使用 ARM64 指令集架構建立 Lambda 函數，務必將命令變更為改用 `--platform linux/arm64` 選項。

### (選用) 在本機測試映像
<a name="ruby-image-test"></a>

1. 使用 **docker run** 命令啟動 Docker 影像。在此範例中，`docker-image` 為映像名稱，`test` 為標籤。

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   此命令將映像作為容器執行，並在 `localhost:9000/2015-03-31/functions/function/invocations` 建立本機端點。
**注意**  
如果您為 ARM64 指令集架構建立 Docker 映像檔，請務必將`--platform linux/arm64`選項改用選項。`--platform linux/amd64`

1. 從新的終端機視窗，將事件張貼至本機端點。

------
#### [ Linux/macOS ]

   在 Linux 或 macOS 中，執行下列 `curl` 命令：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   在 PowerShell 中，執行下列 `Invoke-WebRequest` 命令：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 取得容器 ID。

   ```
   docker ps
   ```

1. 使用 [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 命令停止容器。在此命令中，將 `3766c4ab331c` 替換為上一步驟中的容器 ID。

   ```
   docker kill 3766c4ab331c
   ```

### 部署映像
<a name="ruby-image-deploy"></a>

**若要將映像上傳至 Amazon ECR 並建立 Lambda 函數**

1. 使用 [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 命令，向 Amazon ECR 登錄檔驗證 Docker CLI。
   + 將 `--region`值設定為您要 AWS 區域 在其中建立 Amazon ECR 儲存庫的 。
   + `111122223333` 以您的 AWS 帳戶 ID 取代 。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 使用 [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 命令在 Amazon ECR 中建立儲存庫。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注意**  
Amazon ECR 儲存庫必須與 Lambda 函數位於相同的 AWS 區域 中。

   如果成功，您將會看到以下回應：

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 從上一步驟的輸出中複製 `repositoryUri`。

1. 執行 [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 命令，將 Amazon ECR 儲存庫中的本機映像標記為最新版本。在此命令中：
   + `docker-image:test` 為 Docker 映像檔的名稱和[標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。這是您在 `docker build` 命令中指定的映像名稱和標籤。
   + 將 `<ECRrepositoryUri>` 替換為複製的 `repositoryUri`。確保在 URI 的末尾包含 `:latest`。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   範例：

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 執行 [docker push](https://docs.docker.com/engine/reference/commandline/push/) 命令，將本機映像部署至 Amazon ECR 儲存庫。確保在儲存庫 URI 的末尾包含 `:latest`。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [建立函數的執行角色](lambda-intro-execution-role.md#permissions-executionrole-api) (若您還沒有的話)。在下一個步驟中您需要角色的 Amazon Resource Name (ARN)。

1. 建立 Lambda 函數。對於 `ImageUri`，從之前的設定中指定儲存庫 URI。確保在 URI 的末尾包含 `:latest`。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注意**  
只要映像與 Lambda 函數位於相同的區域，您就可以使用不同 AWS 帳戶中的映像來建立函數。如需詳細資訊，請參閱[Amazon ECR 跨帳戶許可](images-create.md#configuration-images-xaccount-permissions)。

1. 調用函數。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   您應該看到如下回應：

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 若要查看函數的輸出，請檢查 `response.json` 檔案。

若要更新函數程式碼，您必須再次建置映像、將新映像上傳到 Amazon ECR 存放庫，然後使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令將映像部署到 Lambda 函數。

Lambda 會將映像標籤解析為特定映像摘要。這表示如果您將用來部署函數的映像標籤指向 Amazon ECR 中的新映像，Lambda 不會自動更新函數以使用新映像。

若要將新映像部署至相同的 Lambda 函數，必須使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令，即使 Amazon ECR 中的映像標籤保持不變亦如此。在以下範例中，`--publish` 選項會使用更新的容器映像來建立新的函數版本。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

## 透過執行期介面用戶端使用替代基礎映像
<a name="ruby-image-clients"></a>

如果您使用[僅限作業系統的基礎映像](images-create.md#runtimes-images-provided)或替代的基礎映像，則必須在映像中加入執行期介面用戶端。執行期介面用戶端會讓您擴充 [Runtime API](runtimes-api.md)，管理 Lambda 與函數程式碼之間的互動。

使用 RubyGems.org 套件管理員安裝[適用於 Ruby 的 Lambda 執行期介面用戶端](https://rubygems.org/gems/aws_lambda_ric)：

```
gem install aws_lambda_ric
```

您還可以從 GitHub 下載 [Ruby 執行時間介面用戶端](https://github.com/aws/aws-lambda-ruby-runtime-interface-client)。

下列範例示範如何使用非AWS 基礎映像為 Ruby 建置容器映像。範例 Dockerfile 使用官方 Ruby 基礎映像。Dockerfile 包含執行期界面用戶端。

### 先決條件
<a name="ruby-alt-prerequisites"></a>

若要完成本節中的步驟，您必須執行下列各項：
+ [AWS CLI 第 2 版](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (最低版本 25.0.0)
+ Docker [buildx 外掛程式](https://github.com/docker/buildx/blob/master/README.md)。
+ Ruby

### 使用替代基礎映像建立映像
<a name="ruby-alt-create"></a>

**使用替代基礎映像為 Ruby 建立容器映像**

1. 建立專案的目錄，然後切換至該目錄。

   ```
   mkdir example
   cd example
   ```

1. 建立稱為 `Gemfile` 的新檔案。應用程式所需的 RubyGems 套件須列在這裡。可從 RubyGems 適用於 Ruby 的 AWS SDK 取得。您應該選擇要安裝的特定 AWS 服務 Gem 套件。例如，若要使用 [Ruby Gem for Lambda](https://rubygems.org/gems/aws-sdk-lambda/)，您的 Gemfile 看起來應該會像：

   ```
   source 'https://rubygems.org'
   
   gem 'aws-sdk-lambda'
   ```

   或者，[aws-sdk](https://rubygems.org/gems/aws-sdk/) Gem 套件包含每個可用的 AWS 服務 Gem。這個 Gem 非常大，建議您只在依賴許多 AWS 服務時才使用它。

1. 使用[套件安裝作業](https://bundler.io/v2.4/man/bundle-install.1.html)安裝 Gemfile 中指定的相依項。

   ```
   bundle install
   ```

1. 建立稱為 `lambda_function.rb` 的新檔案。您可以將下列範例函數程式碼新增至檔案進行測試，或使用您自己的函數程式碼。  
**Example Ruby 函數**  

   ```
   module LambdaFunction
     class Handler
       def self.process(event:,context:)
         "Hello from Lambda!"
       end
     end
   end
   ```

1. 建立新的 Dockerfile。下列 Dockerfile 使用 Ruby 基礎映像，而非 [AWS  基礎映像](images-create.md#runtimes-images-lp)。Dockerfile 包含 [適用於 Ruby 的執行期介面用戶端](https://github.com/aws/aws-lambda-ruby-runtime-interface-client)，可讓映像與 Lambda 相容。或者，您可以將執行期界面用戶端新增到應用程式的 Gemfile 中。
   + 將 `FROM` 屬性設定為 Ruby 基礎映像。
   + 為函數程式碼建立一個目錄，以及指向該目錄的環境變數。在此範例中，目錄為 `/var/task`，它會鏡像 Lambda 執行環境。不過，您可以選擇函數程式碼的任何目錄，因為 Dockerfile 不使用 AWS 基礎映像。
   + 將 `ENTRYPOINT` 設為您希望 Docker 容器在啟動時執行的模組。在此案例中，模組是執行期界面用戶端。
   + 將 `CMD` 引數設定為 Lambda 函數處理常式。

   請注意，範例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。當您將容器映像部署到 Lambda 時，Lambda 會自動定義一個具有最低權限許可的預設 Linux 使用者。這與標準 Docker 行為不同，後者會在未提供 `USER` 指令時預設為 `root` 使用者。  
**Example Dockerfile**  

   ```
   FROM ruby:2.7
   
   # Install the runtime interface client for Ruby
   RUN gem install aws_lambda_ric
   
   # Add the runtime interface client to the PATH
   ENV PATH="/usr/local/bundle/bin:${PATH}"
   
   # Create a directory for the Lambda function
   ENV LAMBDA_TASK_ROOT=/var/task
   RUN mkdir -p ${LAMBDA_TASK_ROOT}
   WORKDIR ${LAMBDA_TASK_ROOT}
   
   # Copy Gemfile and Gemfile.lock
   COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}/
   
   # Install Bundler and the specified gems
   RUN gem install bundler:2.4.20 && \
       bundle config set --local path 'vendor/bundle' && \
       bundle install
   
   # Copy function code
   COPY lambda_function.rb ${LAMBDA_TASK_ROOT}/    
   
   # Set runtime interface client as default command for the container runtime
   ENTRYPOINT [ "aws_lambda_ric" ]
   
   # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
   CMD [ "lambda_function.LambdaFunction::Handler.process" ]
   ```

1. 使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令建立 Docker 映像檔。以下範例將映像命名為 `docker-image` 並為其提供 `test` [標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。若要使映像與 Lambda 相容，必須使用 `--provenance=false` 選項。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注意**  
此命令會指定 `--platform linux/amd64` 選項，確保無論建置機器的架構為何，您的容器都與 Lambda 執行環境相容。如果您打算使用 ARM64 指令集架構建立 Lambda 函數，務必將命令變更為改用 `--platform linux/arm64` 選項。

### (選用) 在本機測試映像
<a name="ruby-alt-test"></a>

使用 [執行期界面模擬器](https://github.com/aws/aws-lambda-runtime-interface-emulator/) 以在本機測試映像。您可以[將模擬器建置到映像中](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image)，也可以使用以下步驟，將其安裝在本機電腦。

**若要在本機電腦上安裝並執行執行期介面模擬器**

1. 在您的專案目錄中執行以下命令，從 GitHub 下載執行期介面模擬器 (x86-64 架構)，並安裝在本機電腦上。

------
#### [ Linux/macOS ]

   ```
   mkdir -p ~/.aws-lambda-rie && \
       curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \
       chmod +x ~/.aws-lambda-rie/aws-lambda-rie
   ```

   若要安裝 arm64 模擬器，請將上一個命令中的 GitHub 儲存庫 URL 替換為以下內容：

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------
#### [ PowerShell ]

   ```
   $dirPath = "$HOME\.aws-lambda-rie"
   if (-not (Test-Path $dirPath)) {
       New-Item -Path $dirPath -ItemType Directory
   }
         
   $downloadLink = "https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie"
   $destinationPath = "$HOME\.aws-lambda-rie\aws-lambda-rie"
   Invoke-WebRequest -Uri $downloadLink -OutFile $destinationPath
   ```

   若要安裝 arm64 模擬器，請將 `$downloadLink` 更換為下列項目：

   ```
   https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie-arm64
   ```

------

1. 使用 **docker run** 命令啟動 Docker 影像。注意下列事項：
   + `docker-image` 是映像名稱，而 `test` 是標籤。
   + `aws_lambda_ric lambda_function.LambdaFunction::Handler.process` 是 Dockerfile 中的 `ENTRYPOINT`，後面接著 `CMD`。

------
#### [ Linux/macOS ]

   ```
   docker run --platform linux/amd64 -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
       --entrypoint /aws-lambda/aws-lambda-rie \
       docker-image:test \
           aws_lambda_ric lambda_function.LambdaFunction::Handler.process
   ```

------
#### [ PowerShell ]

   ```
   docker run --platform linux/amd64 -d -v "$HOME\.aws-lambda-rie:/aws-lambda" -p 9000:8080 `
   --entrypoint /aws-lambda/aws-lambda-rie `
   docker-image:test `
       aws_lambda_ric lambda_function.LambdaFunction::Handler.process
   ```

------

   此命令將映像作為容器執行，並在 `localhost:9000/2015-03-31/functions/function/invocations` 建立本機端點。
**注意**  
如果您為 ARM64 指令集架構建立 Docker 映像檔，請務必將`--platform linux/arm64`選項改用選項。`--platform linux/amd64`

1. 將事件張貼至本機端點。

------
#### [ Linux/macOS ]

   在 Linux 或 macOS 中，執行下列 `curl` 命令：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   在 PowerShell 中，執行下列 `Invoke-WebRequest` 命令：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 取得容器 ID。

   ```
   docker ps
   ```

1. 使用 [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 命令停止容器。在此命令中，將 `3766c4ab331c` 替換為上一步驟中的容器 ID。

   ```
   docker kill 3766c4ab331c
   ```

### 部署映像
<a name="ruby-alt-deploy"></a>

**若要將映像上傳至 Amazon ECR 並建立 Lambda 函數**

1. 使用 [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 命令，向 Amazon ECR 登錄檔驗證 Docker CLI。
   + 將 `--region`值設定為您要 AWS 區域 在其中建立 Amazon ECR 儲存庫的 。
   + `111122223333` 以您的 AWS 帳戶 ID 取代 。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 使用 [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 命令在 Amazon ECR 中建立儲存庫。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注意**  
Amazon ECR 儲存庫必須與 Lambda 函數位於相同的 AWS 區域 中。

   如果成功，您將會看到以下回應：

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 從上一步驟的輸出中複製 `repositoryUri`。

1. 執行 [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 命令，將 Amazon ECR 儲存庫中的本機映像標記為最新版本。在此命令中：
   + `docker-image:test` 為 Docker 映像檔的名稱和[標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。這是您在 `docker build` 命令中指定的映像名稱和標籤。
   + 將 `<ECRrepositoryUri>` 替換為複製的 `repositoryUri`。確保在 URI 的末尾包含 `:latest`。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   範例：

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 執行 [docker push](https://docs.docker.com/engine/reference/commandline/push/) 命令，將本機映像部署至 Amazon ECR 儲存庫。確保在儲存庫 URI 的末尾包含 `:latest`。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [建立函數的執行角色](lambda-intro-execution-role.md#permissions-executionrole-api) (若您還沒有的話)。在下一個步驟中您需要角色的 Amazon Resource Name (ARN)。

1. 建立 Lambda 函數。對於 `ImageUri`，從之前的設定中指定儲存庫 URI。確保在 URI 的末尾包含 `:latest`。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注意**  
只要映像與 Lambda 函數位於相同的區域，您就可以使用不同 AWS 帳戶中的映像來建立函數。如需詳細資訊，請參閱[Amazon ECR 跨帳戶許可](images-create.md#configuration-images-xaccount-permissions)。

1. 調用函數。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   您應該看到如下回應：

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 若要查看函數的輸出，請檢查 `response.json` 檔案。

若要更新函數程式碼，您必須再次建置映像、將新映像上傳到 Amazon ECR 存放庫，然後使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令將映像部署到 Lambda 函數。

Lambda 會將映像標籤解析為特定映像摘要。這表示如果您將用來部署函數的映像標籤指向 Amazon ECR 中的新映像，Lambda 不會自動更新函數以使用新映像。

若要將新映像部署至相同的 Lambda 函數，必須使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令，即使 Amazon ECR 中的映像標籤保持不變亦如此。在以下範例中，`--publish` 選項會使用更新的容器映像來建立新的函數版本。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

# 針對 Ruby Lambda 函數使用層
<a name="ruby-layers"></a>

使用 [Lambda 層](chapter-layers.md)封裝要在多個函式之間重複使用的程式碼與相依項。層通常具備程式庫相依性、[自訂執行期](runtimes-custom.md)或組態檔案。建立層包含三個一般步驟：

1. 封裝層內容。這表示建立 .zip 封存檔，其中包含您要在函數中使用的相依項。

1. 在 Lambda 中建立層。

1. 將層新增至函數中。

**Topics**
+ [

## 封裝層內容
](#ruby-layers-package)
+ [

## 在 Lambda 中建立層
](#publishing-layer)
+ [

## 在函式中使用來自層的 gem
](#ruby-layers-bundler-limitations)
+ [

## 將層新增至函式
](#ruby-layer-adding)
+ [

## 應用程式範例
](#ruby-layer-sample-app)

## 封裝層內容
<a name="ruby-layers-package"></a>

若要建立層，請將套件封裝成符合以下要求的 .zip 壓縮檔：
+ 使用計劃用於 Lambda 函式的相同 Ruby 版本來建立層。例如，若針對 Ruby 3.4 建立層，需為函式使用 Ruby 3.4 執行時期。
+ 層的 .zip 檔案必須使用下列任一目錄結構：
  + `ruby/gems/x.x.x` (其中 *x.x.x* 表示 Ruby 版本，例如 `3.4.0`)
  + `ruby/lib`

  如需更多詳細資訊，請參閱 [每個 Lambda 執行時間的層路徑](packaging-layers.md#packaging-layers-paths)。
+ 層中的套件必須與 Linux 相容。Lambda 函式會在 Amazon Linux 上執行。

您可以建立包含第三方 Ruby gem 或您自訂 Ruby 模組與類別的層。許多熱門的 Ruby gem 都包含必須針對 Lambda Linux 環境編譯的原生延伸模組 (C 程式碼)。

### 純 Ruby gem
<a name="ruby-layers-pure-ruby-gems"></a>

純 Ruby gem 僅包含 Ruby 程式碼，不需要編譯。這些 gem 更易於封裝，可在不同平台上運作。

**使用純 Ruby gem 建立層**

1. 建立 `Gemfile`，指定要包含在層中的純 Ruby gem：  
**Example Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'tzinfo'
   ```

1. 使用封裝程式將 gem 安裝至 `vendor/bundle` 目錄：

   ```
   bundle config set --local path vendor/bundle
   bundle install
   ```

1. 將已安裝的 gem 複製至 Lambda 所需的目錄結構 (`ruby/gems/3.4.0`)：

   ```
   mkdir -p ruby/gems/3.4.0
   cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   ```

1. 壓縮層內容：

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   .zip 檔案的目錄結構應如下所示：

   ```
   ruby/              
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── concurrent-ruby-1.3.5/
           │   └── tzinfo-2.0.6/
           ├── specifications/
           ├── cache/
           ├── build_info/
           └── (other bundler directories)
   ```
**注意**  
必須在函式程式碼中個別要求每個 gem。不能使用 `bundler/setup` 或 `Bundler.require`。如需更多詳細資訊，請參閱 [在函式中使用來自層的 gem](#ruby-layers-bundler-limitations)。

### 帶有原生延伸模組的 gem
<a name="ruby-layers-native-extensions"></a>

許多熱門的 Ruby gem 都包含必須針對目標平台編譯的原生延伸模組 (C 程式碼)。帶有原生延伸模組的熱門 gem 包括 [nokogiri](https://rubygems.org/gems/nokogiri/)、[pg](https://rubygems.org/gems/pg/)、[mysql2](https://rubygems.org/gems/mysql2/)、[sqlite3](https://rubygems.org/gems/sqlite3/) 和 [ffi](https://rubygems.org/gems/ffi/)。這些 gem 必須在與 Lambda 執行時期相容的 Linux 環境中建置。

**使用帶有原生延伸模組的 gem 建立層**

1. 建立 `Gemfile`。  
**Example Gemfile**  

   ```
   source 'https://rubygems.org'
   
   gem 'nokogiri'
   gem 'httparty'
   ```

1. 使用 Docker，在與 Lambda 相容的 Linux 環境中建置 gem。在 Dockerfile 中指定 [AWS 基礎映像](ruby-image.md#ruby-image-base)：  
**Example 適用於 Ruby 3.4 的 Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/ruby:3.4
   
   # Copy Gemfile
   COPY Gemfile ./
   
   # Install system dependencies for native extensions
   RUN dnf update -y && \
       dnf install -y gcc gcc-c++ make
   
   # Configure bundler and install gems
   RUN bundle config set --local path vendor/bundle && \
       bundle install
   
   # Create the layer structure
   RUN mkdir -p ruby/gems/3.4.0 && \
       cp -r vendor/bundle/ruby/3.4.0*/* ruby/gems/3.4.0/
   
   # Create the layer zip file
   RUN zip -r layer.zip ruby/
   ```

1. 建置映像並擷取層：

   ```
   docker build -t ruby-layer-builder .
   docker run --rm -v $(pwd):/output --entrypoint cp ruby-layer-builder layer.zip /output/
   ```

   這會在正確的 Linux 環境中建置 gem，並將 `layer.zip` 檔案複製至本機目錄。.zip 檔案的目錄結構應如下所示：

   ```
   ruby/
   └── gems/
       └── 3.4.0/
           ├── gems/
           │   ├── bigdecimal-3.2.2/
           │   ├── csv-3.3.5/
           │   ├── httparty-0.23.1/
           │   ├── mini_mime-1.1.5/
           │   ├── multi_xml-0.7.2/
           │   ├── nokogiri-1.18.8-x86_64-linux-gnu/
           │   └── racc-1.8.1/
           ├── build_info/
           ├── cache/
           ├── specifications/
           └── (other bundler directories)
   ```
**注意**  
必須在函式程式碼中個別要求每個 gem。不能使用 `bundler/setup` 或 `Bundler.require`。如需更多詳細資訊，請參閱 [在函式中使用來自層的 gem](#ruby-layers-bundler-limitations)。

### 自訂 Ruby 模組
<a name="custom-ruby-modules"></a>

**使用自訂的程式碼建立層**

1. 建立層所需的目錄結構：

   ```
   mkdir -p ruby/lib
   ```

1. 在 `ruby/lib` 目錄中建立 Ruby 模組。下列模組範例透過確認訂單包含所需資訊來驗證訂單。  
**Example ruby/lib/order\$1validator.rb**  

   ```
   require 'json'
   
   module OrderValidator
     class ValidationError < StandardError; end
   
     def self.validate_order(order_data)
       # Validates an order and returns formatted data
       required_fields = %w[product_id quantity]
       
       # Check required fields
       missing_fields = required_fields.reject { |field| order_data.key?(field) }
       unless missing_fields.empty?
         raise ValidationError, "Missing required fields: #{missing_fields.join(', ')}"
       end
       
       # Validate quantity
       quantity = order_data['quantity']
       unless quantity.is_a?(Integer) && quantity > 0
         raise ValidationError, 'Quantity must be a positive integer'
       end
       
       # Format and return the validated data
       {
         'product_id' => order_data['product_id'].to_s,
         'quantity' => quantity,
         'shipping_priority' => order_data.fetch('priority', 'standard')
       }
     end
   
     def self.format_response(status_code, body)
       # Formats the API response
       {
         statusCode: status_code,
         body: JSON.generate(body)
       }
     end
   end
   ```

1. 壓縮層內容：

------
#### [ Linux/macOS ]

   ```
   zip -r layer.zip ruby/
   ```

------
#### [ PowerShell ]

   ```
   Compress-Archive -Path .\ruby -DestinationPath .\layer.zip
   ```

------

   .zip 檔案的目錄結構應如下所示：

   ```
   ruby/              
   └── lib/
       └── order_validator.rb
   ```

1. 在函式中，要求並使用這些模組。必須在函式程式碼中個別要求每個 gem。不能使用 `bundler/setup` 或 `Bundler.require`。如需更多詳細資訊，請參閱 [在函式中使用來自層的 gem](#ruby-layers-bundler-limitations)。範例：

   ```
   require 'json'
   require 'order_validator'
   
   def lambda_handler(event:, context:)
     begin
       # Parse the order data from the event body
       order_data = JSON.parse(event['body'] || '{}')
       
       # Validate and format the order
       validated_order = OrderValidator.validate_order(order_data)
       
       OrderValidator.format_response(200, {
         message: 'Order validated successfully',
         order: validated_order
       })
     rescue OrderValidator::ValidationError => e
       OrderValidator.format_response(400, {
         error: e.message
       })
     rescue => e
       OrderValidator.format_response(500, {
         error: 'Internal server error'
       })
     end
   end
   ```

   您可以使用下列[測試事件](testing-functions.md#invoke-with-event)來調用函式：

   ```
   {
       "body": "{\"product_id\": \"ABC123\", \"quantity\": 2, \"priority\": \"express\"}"
   }
   ```

   預期回應：

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"Order validated successfully\",\"order\":{\"product_id\":\"ABC123\",\"quantity\":2,\"shipping_priority\":\"express\"}}"
   }
   ```

## 在 Lambda 中建立層
<a name="publishing-layer"></a>

您可以使用 AWS CLI 或 Lambda 主控台來發布層。

------
#### [ AWS CLI ]

執行 [publish-layer-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-layer-version.html) AWS CLI 命令來建立 Lambda 層：

```
aws lambda publish-layer-version --layer-name my-layer --zip-file fileb://layer.zip --compatible-runtimes ruby3.4
```

[相容的執行時期](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)參數為選用參數。指定此參數後，Lambda 會據此在 Lambda 主控台中篩選層。

------
#### [ Console ]

**建立圖層 (主控台)**

1. 開啟 Lambda 主控台中的 [層頁面](https://console.aws.amazon.com/lambda/home#/layers)。

1. 選擇 **建立圖層**。

1. 選擇**上傳 .zip 檔案**，然後上傳先前建立的 .zip 壓縮檔。

1. (選用) 在**相容的執行時期**欄位中，選擇與用於建置層的 Ruby 版本相對應的 Ruby 執行時期。

1. 選擇**建立**。

------

## 在函式中使用來自層的 gem
<a name="ruby-layers-bundler-limitations"></a>

在函式程式碼中，必須明確要求要使用的每個 gem。不支援 `bundler/setup` 和 `Bundler.require` 等封裝程式命令。以下是在 Lambda 函式中正確使用來自層的 gem 的執行方法：

```
# Correct: Use explicit requires for each gem
require 'nokogiri'
require 'httparty'

def lambda_handler(event:, context:)
  # Use the gems directly
  doc = Nokogiri::HTML(event['html'])
  response = HTTParty.get(event['url'])
  # ... rest of your function
end

# Incorrect: These Bundler commands will not work
# require 'bundler/setup'
# Bundler.require
```

## 將層新增至函式
<a name="ruby-layer-adding"></a>

------
#### [ AWS CLI ]

若要將層連接至函式，請執行 [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) AWS CLI 命令。對於 `--layers` 參數，請使用層 ARN。ARN 必須指定版本 (例如 `arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1`)。如需更多詳細資訊，請參閱 [層和層的版本](chapter-layers.md#lambda-layer-versions)。

```
aws lambda update-function-configuration --function-name my-function --cli-binary-format raw-in-base64-out --layers "arn:aws:lambda:us-east-1:123456789012:layer:my-layer:1"
```

如果您使用 AWS CLI 第 2 版，則需要 **cli-binary-format** 選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。

------
#### [ Console ]

**將層新增至函式**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇函式。

1. 向下捲動至**層**區段，然後選擇**新增層**。

1. 在**選擇層**欄位中，選取**自訂層**，然後選擇要使用的層。
**注意**  
如果未在建立層時新增[相容的執行時期](https://docs.aws.amazon.com/lambda/latest/api/API_PublishLayerVersion.html#lambda-PublishLayerVersion-request-CompatibleRuntimes)，此處不會列出層。您可以改為指定層 ARN。

1. 選擇**新增**。

------

## 應用程式範例
<a name="ruby-layer-sample-app"></a>

如需如何使用 Lambda 層的更多範例，請參閱 AWS Lambda Developer Guide GitHub repository 中的 [layer-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/layer-ruby) 範例應用程式。此應用程式包含一個內含 [tzinfo](https://rubygems.org/gems/tzinfo) 程式庫的層。建立層之後，您可以部署並調用相應的函式，驗證層是否如預期那樣運作。

# 使用 Lambda 內容物件擷取 Ruby 函數資訊
<a name="ruby-context"></a>

當 Lambda 執行您的函數時，它會將內容物件傳遞至[處理常式](ruby-handler.md)。此物件提供的方法和各項屬性提供了有關調用、函式以及執行環境的資訊。

**內容方法**
+ `get_remaining_time_in_millis` - 傳回執行逾時前剩餘的毫秒數。

**內容屬性**
+ `function_name` – Lambda 函數的名稱。
+ `function_version` – 函數的[版本](configuration-versions.md)。
+ `invoked_function_arn` - 用於叫用此函數的 Amazon Resource Name (ARN)。指出調用者是否指定版本號或別名。
+ `memory_limit_in_mb` - 分配給函數的記憶體數量。
+ `aws_request_id` - 調用請求的識別符。
+ `log_group_name` - 函數的日誌群組。
+ `log_stream_name` - 函數執行個體的記錄串流。
+ `deadline_ms` - 執行逾時的日期，以 Unix 時間毫秒為單位。
+ `identity` - (行動應用程式) 已授權請求的 Amazon Cognito 身分的相關資訊。
+ `client_context` - (行動應用程式) 用戶端應用程式提供給 Lambda 的用戶端內容。

# 記錄和監控 Ruby Lambda 函數
<a name="ruby-logging"></a>

AWS Lambda 會自動代表您監控 Lambda 函數，並將日誌傳送至 Amazon CloudWatch。您的 Lambda 函數隨附有 CloudWatch Logs 日誌群組，且函數的每一執行個體各有一個日誌串流。Lambda 執行期環境會將每次調用的詳細資訊傳送至日誌串流，並且轉傳來自函數程式碼的日誌及其他輸出。如需詳細資訊，請參閱[將 Lambda 函式日誌傳送至 CloudWatch Logs](monitoring-cloudwatchlogs.md)。

此頁面說明如何從 Lambda 函數的程式碼產生日誌輸出，並使用 AWS Command Line Interface、Lambda 主控台或 CloudWatch 主控台存取日誌。

**Topics**
+ [

## 建立傳回日誌的函數
](#ruby-logging-output)
+ [

## 在 Lambda 主控台檢視日誌
](#ruby-logging-console)
+ [

## 在 CloudWatch 主控台中檢視 記錄
](#ruby-logging-cwconsole)
+ [

## 使用 AWS Command Line Interface (AWS CLI) 檢視日誌
](#ruby-logging-cli)
+ [

## 刪除日誌
](#ruby-logging-delete)
+ [

## 使用 Ruby 記錄程式庫
](#ruby-logging-lib)

## 建立傳回日誌的函數
<a name="ruby-logging-output"></a>

若要由您的函式程式碼輸出日誌，可使用 `puts` 陳述式或者任何能夠寫入 `stdout` 或 `stderr` 的記錄程式庫。下列範例會記錄環境變數和事件物件的值。

**Example lambda\$1function.rb**  

```
# lambda_function.rb

def handler(event:, context:)
    puts "## ENVIRONMENT VARIABLES"
    puts ENV.to_a
    puts "## EVENT"
    puts event.to_a
end
```

**Example 記錄格式**  

```
START RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95 Version: $LATEST
## ENVIRONMENT VARIABLES
environ({'AWS_LAMBDA_LOG_GROUP_NAME': '/aws/lambda/my-function', 'AWS_LAMBDA_LOG_STREAM_NAME': '2020/01/31/[$LATEST]3893xmpl7fac4485b47bb75b671a283c', 'AWS_LAMBDA_FUNCTION_NAME': 'my-function', ...})
## EVENT
{'key': 'value'}
END RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95
REPORT RequestId: 8f507cfc-xmpl-4697-b07a-ac58fc914c95  Duration: 15.74 ms  Billed Duration: 147 ms Memory Size: 128 MB Max Memory Used: 56 MB  Init Duration: 130.49 ms
XRAY TraceId: 1-5e34a614-10bdxmplf1fb44f07bc535a1   SegmentId: 07f5xmpl2d1f6f85 Sampled: true
```

Ruby 執行時間會記錄每次調用的 `START`、`END` 和 `REPORT` 行。報告明細行提供下列詳細資訊。

**REPORT 行資料欄位**
+ **RequestId** - 進行調用的唯一請求 ID。
+ **持續時間** - 函數的處理常式方法處理事件所花費的時間量。
+ **計費持續時間** - 調用的計費時間量。
+ **記憶體大小** - 分配給函數的記憶體數量。
+ **使用的記憶體上限** - 函數所使用的記憶體數量。當調用共用執行環境時，Lambda 會報告所有調用使用的記憶體上限。此行為可能會導致報告值高於預期值。
+ **初始化持續時間** - 對於第一個提供的請求，這是執行期載入函數並在處理常式方法之外執行程式碼所花費的時間量。
+ **XRAY TraceId** - 對於追蹤的請求，這是 [AWS X-Ray 追蹤 ID](services-xray.md)。
+ **SegmentId** - 對於追蹤的請求，這是 X-Ray 區段 ID。
+ **已取樣** - 對於追蹤的請求，這是取樣結果。

如需更詳細的日誌，請使用 [使用 Ruby 記錄程式庫](#ruby-logging-lib)。

## 在 Lambda 主控台檢視日誌
<a name="ruby-logging-console"></a>

您可以在調用 Lambda 函數之後，使用 Lambda 主控台來檢視日誌輸出。

如果可以從內嵌**程式碼**編輯器測試您的程式碼，您會在**執行結果**中找到日誌。使用主控台測試功能以調用函數時，您會在**詳細資訊**區段找到**日誌輸出**。

## 在 CloudWatch 主控台中檢視 記錄
<a name="ruby-logging-cwconsole"></a>

您可以使用 Amazon CloudWatch 主控台來檢視所有 Lambda 函數調用的日誌。

**若要在 CloudWatch 主控台上檢視日誌**

1. 在 CloudWatch 主控台上開啟[日誌群組頁面](https://console.aws.amazon.com/cloudwatch/home?#logs:)。

1. 選擇您的函數的日誌群組 (**/aws/lambda/*your-function-name***)。

1. 選擇日誌串流

每個日誌串流都會對應至[函式的執行個體](lambda-runtime-environment.md)。當您更新 Lambda 函數，以及建立其他執行個體以處理並行調用時，就會顯示日誌串流。若要尋找特定調用的日誌，建議您使用 檢測函數 AWS X-Ray。X-Ray 會在追蹤內記錄有關請求和日誌串流的詳細資訊。

## 使用 AWS Command Line Interface (AWS CLI) 檢視日誌
<a name="ruby-logging-cli"></a>

是一種 AWS CLI 開放原始碼工具，可讓您使用命令列 Shell 中的 命令與 AWS 服務互動。若要完成本節中的步驟，您必須擁有 [AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

您可以透過 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)，使用 `--log-type` 命令選項來擷取要調用的日誌。其回應將包含 `LogResult` 欄位，內含該次調用的 base64 編碼日誌 (最大達 4 KB)。

**Example 擷取日誌 ID**  
下列範例顯示如何從名稱為 `my-function` 的函數的 `LogResult` 欄位來擷取*日誌 ID*。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
您應該會看到下列輸出：  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example 解碼日誌**  
在相同的命令提示中，使用 `base64` 公用程式來解碼日誌。下列範例顯示如何擷取 `my-function` 的 base64 編碼日誌。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
如果您使用的是第 2 AWS CLI 版，則需要 **cli-binary-format**選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  
您應該會看到下列輸出：  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
該 `base64` 公用程式可在 Linux、macOS 和 [Ubuntu on Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10) 上使用。macOS 使用者可能需要使用 `base64 -D`。

**Example get-logs.sh 指令碼**  
在相同的命令提示中，使用下列指令碼下載最後五個日誌事件。該指令碼使用 `sed` 以從輸出檔案移除引述，並休眠 15 秒以使日誌可供使用。輸出包括來自 Lambda 的回應以及來自 `get-log-events` 命令的輸出。  
複製下列程式碼範例的內容，並將您的 Lambda 專案目錄儲存為 `get-logs.sh`。  
如果您使用的是第 2 AWS CLI 版，則需要 **cli-binary-format**選項。若要讓此成為預設的設定，請執行 `aws configure set cli-binary-format raw-in-base64-out`。若要取得更多資訊，請參閱*《AWS Command Line Interface 使用者指南第 2 版》*中 [AWS CLI 支援的全域命令列選項](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)。  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS 和 Linux (僅限)**  
在相同的命令提示中，macOS 和 Linux 使用者可能需要執行下列命令，以確保指令碼可執行。  

```
chmod -R 755 get-logs.sh
```

**Example 擷取最後五個記錄事件**  
在相同的命令提示中，執行下列指令碼以取得最後五個日誌事件。  

```
./get-logs.sh
```
您應該會看到下列輸出：  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## 刪除日誌
<a name="ruby-logging-delete"></a>

當您刪除函數時，不會自動刪除日誌群組。若要避免無限期地儲存日誌，請刪除日誌群組，或[設定保留期間](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)，系統會在該時間之後自動刪除日誌。

## 使用 Ruby 記錄程式庫
<a name="ruby-logging-lib"></a>

Ruby [記錄程式庫](https://ruby-doc.org/stdlib-2.7.0/libdoc/logger/rdoc/index.html)會傳回易於讀取的精簡日誌。使用記錄公用程式輸出與函數相關的詳細資訊、訊息和錯誤碼。

```
# lambda_function.rb

require 'logger'

def handler(event:, context:) 
  logger = Logger.new($stdout)
  logger.info('## ENVIRONMENT VARIABLES')
  logger.info(ENV.to_a)
  logger.info('## EVENT')
  logger.info(event)
  event.to_a
end
```

來自 `logger` 的輸出包含記錄等級、時間戳記和請求 ID。

```
START RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125 Version: $LATEST
[INFO]  2020-01-31T22:12:58.534Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    ## ENVIRONMENT VARIABLES

[INFO]  2020-01-31T22:12:58.534Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    environ({'AWS_LAMBDA_LOG_GROUP_NAME': '/aws/lambda/my-function', 'AWS_LAMBDA_LOG_STREAM_NAME': '2020/01/31/[$LATEST]1bbe51xmplb34a2788dbaa7433b0aa4d', 'AWS_LAMBDA_FUNCTION_NAME': 'my-function', ...})

[INFO]  2020-01-31T22:12:58.535Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    ## EVENT

[INFO]  2020-01-31T22:12:58.535Z    1c8df7d3-xmpl-46da-9778-518e6eca8125    {'key': 'value'}

END RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125
REPORT RequestId: 1c8df7d3-xmpl-46da-9778-518e6eca8125  Duration: 2.75 ms   Billed Duration: 117 ms Memory Size: 128 MB Max Memory Used: 56 MB  Init Duration: 113.51 ms
XRAY TraceId: 1-5e34a66a-474xmpl7c2534a87870b4370   SegmentId: 073cxmpl3e442861 Sampled: true
```

# 在 中檢測 Ruby 程式碼 AWS Lambda
<a name="ruby-tracing"></a>

Lambda 與 整合 AWS X-Ray ，可讓您追蹤、偵錯和最佳化 Lambda 應用程式。您可以使用 X-Ray 來追踪請求，因為它會周遊應用程式中的資源，從前端 API 到後端的存儲體和資料庫。只要將 X-Ray SDK 程式庫新增至建置組態，您就可以記錄函數對 AWS 服務所做的任何呼叫的錯誤和延遲。

設定主動追蹤之後，您可以透過應用程式來觀察特定請求。[X-Ray 服務圖](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts-servicegraph)顯示了有關應用程式及其所有元件的資訊。下列範例顯示了一個具有兩個函數的應用程式。主要函式會處理事件，有時會傳回錯誤。頂端的第二個函數會處理出現在第一個日誌群組中的錯誤，並使用 AWS SDK 呼叫 X-Ray、Amazon Simple Storage Service (Amazon S3) 和 Amazon CloudWatch Logs。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/sample-errorprocessor-servicemap.png)


若要使用控制台在 Lambda 函數上切換主動追蹤，請按照下列步驟操作：

**開啟主動追蹤**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇一個函數。

1. 選擇**組態**，然後選擇**監控和操作工具**。

1. 在**其他監控工具**欄位中，選擇**編輯**。

1. 在 **CloudWatch Application Signals 和 AWS X-Ray** 下，選擇**啟用** **Lambda 服務追蹤**。

1. 選擇**儲存**。

**定價**  
您可以在每月免費使用 X-Ray 追蹤，最高可達特定限制，作為 AWS 免費方案的一部分。達到閾值後，X-Ray 會收取追蹤儲存及擷取的費用。如需詳細資訊，請參閱 [AWS X-Ray 定價](https://aws.amazon.com/xray/pricing/)。

您的函數需要將追蹤資料上傳至 X-Ray 的許可。當您在 Lambda 主控台中啟用追蹤時，Lambda 會將必要的許可新增至函數的[執行角色](lambda-intro-execution-role.md)。否則，請將 [AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess) 政策新增至執行角色。

X-Ray 無法追蹤應用程式的所有請求。X-Ray 會套用取樣演算法以確保追蹤的效率，同時仍提供所有請求的代表範本。取樣率為每秒 1 次請求和 5% 的額外請求。不能針對函數設定 X-Ray 取樣率。

在 X-Ray 中，*追蹤*會記錄一或多個*服務*所處理之要求的相關資訊。Lambda 會在每個追蹤上記錄 2 個區段，這會在服務圖表上建立兩個節點。下圖反白顯示了這兩個節點：

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/xray-servicemap-function.png)


左側第一個節點代表接收調用請求的 Lambda 服務。第二個節點代表您特定的 Lambda 函數。下列範例顯示了具有這 2 個區段的追蹤。兩者都被命名為 **my-function**，但其中之一的來源為 `AWS::Lambda`，而另一個的來源為 `AWS::Lambda::Function`。如果 `AWS::Lambda` 區段顯示錯誤，Lambda 服務就會出現問題。如果 `AWS::Lambda::Function` 區段顯示錯誤，表示您的函數出現了問題。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


此範例會展開 `AWS::Lambda::Function` 區段以顯示其三個子區段：

**注意**  
AWS 目前正在對 Lambda 服務實作變更。由於這些變更，您可能會看到系統日誌訊息的結構和內容，與 AWS 帳戶中不同 Lambda 函數發出的追蹤區段之間存在細微差異。  
此處顯示的追蹤範例說明了舊式函數區段。下列段落說明了舊式和新式區段之間的差異。  
這些變化將在未來幾週內實作，除中國和 GovCloud 區域以外，所有 AWS 區域 中的所有函數都會轉換至使用新格式的日誌訊息和追蹤區段。

舊式函數區段包含下列子區段：
+ **初始化** - 表示載入函數和執行[初始化程式碼](foundation-progmodel.md)所花費的時間。只有函數的每個執行個體所處理的第一個事件會顯示此子區段。
+ **調用** – 表示執行處理常式程式碼所花費的時間。
+ **額外負荷** - 表示 Lambda 執行期為做好準備以處理下一個事件所花費的時間。

新式函數區段不包含 `Invocation` 子區段。相反地，客戶子區段會直接連接至函數區段。如需舊式和新式函數區段結構的詳細資訊，請參閱[了解 X-Ray 追蹤](services-xray.md#services-xray-traces)。

您可以測試處理常式程式碼，以記錄中繼資料並追蹤下游呼叫。若要記錄處理常式對其他資源和服務所進行之呼叫的詳細資料，請使用適用於 Ruby 的 X-Ray 開發套件。若要取得開發套件，請將 `aws-xray-sdk` 套件新增至應用程式的相依性。

**Example [blank-ruby/function/Gemfile](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/function/Gemfile)**  

```
# Gemfile
source 'https://rubygems.org'

gem 'aws-xray-sdk', '0.11.4'
gem 'aws-sdk-lambda', '1.39.0'
gem 'test-unit', '3.3.5'
```

若要檢測 AWS SDK 用戶端，請在初始化程式碼中建立用戶端後要求 `aws-xray-sdk/lambda`模組。

**Example [blank-ruby/function/lambda\$1function.rb](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/function/lambda_function.rb) – 追蹤 AWS SDK 用戶端**  

```
# lambda_function.rb
require 'logger'
require 'json'
require 'aws-sdk-lambda'
$client = Aws::Lambda::Client.new()
$client.get_account_settings()

require 'aws-xray-sdk/lambda'

def lambda_handler(event:, context:)
  logger = Logger.new($stdout)
  ...
```

在 X-Ray 中，*追蹤*會記錄一或多個*服務*所處理之要求的相關資訊。Lambda 會在每個追蹤上記錄 2 個區段，這會在服務圖表上建立兩個節點。下圖反白顯示了這兩個節點：

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/xray-servicemap-function.png)


左側第一個節點代表接收調用請求的 Lambda 服務。第二個節點代表您特定的 Lambda 函數。下列範例顯示了具有這 2 個區段的追蹤。兩者都被命名為 **my-function**，但其中之一的來源為 `AWS::Lambda`，而另一個的來源為 `AWS::Lambda::Function`。如果 `AWS::Lambda` 區段顯示錯誤，Lambda 服務就會出現問題。如果 `AWS::Lambda::Function` 區段顯示錯誤，表示您的函數出現了問題。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


此範例會展開 `AWS::Lambda::Function` 區段以顯示其三個子區段：

**注意**  
AWS 目前正在對 Lambda 服務實作變更。由於這些變更，您可能會看到系統日誌訊息的結構和內容，與 AWS 帳戶中不同 Lambda 函數發出的追蹤區段之間存在細微差異。  
此處顯示的追蹤範例說明了舊式函數區段。下列段落說明了舊式和新式區段之間的差異。  
這些變化將在未來幾週內實作，除中國和 GovCloud 區域以外，所有 AWS 區域 中的所有函數都會轉換至使用新格式的日誌訊息和追蹤區段。

舊式函數區段包含下列子區段：
+ **初始化** - 表示載入函數和執行[初始化程式碼](foundation-progmodel.md)所花費的時間。只有函數的每個執行個體所處理的第一個事件會顯示此子區段。
+ **調用** – 表示執行處理常式程式碼所花費的時間。
+ **額外負荷** - 表示 Lambda 執行期為做好準備以處理下一個事件所花費的時間。

新式函數區段不包含 `Invocation` 子區段。相反地，客戶子區段會直接連接至函數區段。如需舊式和新式函數區段結構的詳細資訊，請參閱[了解 X-Ray 追蹤](services-xray.md#services-xray-traces)。

您也可以檢測 HTTP 用戶端、記錄 SQL 查詢，以及建立具有註釋和中繼資料的自訂子區段。如需詳細資訊，請參閱[《 開發人員指南》中的適用於 Ruby 的 X-Ray 開發套件](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-ruby.html)。 AWS X-Ray 

**Topics**
+ [

## 透過 Lambda API 啟用主動追蹤
](#ruby-tracing-api)
+ [

## 使用 啟用主動追蹤 CloudFormation
](#ruby-tracing-cloudformation)
+ [

## 將執行時間相依性儲存在圖層中
](#ruby-tracing-layers)

## 透過 Lambda API 啟用主動追蹤
<a name="ruby-tracing-api"></a>

若要使用 AWS CLI 或 AWS SDK 管理追蹤組態，請使用下列 API 操作：
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html)
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)

下列範例 AWS CLI 命令會在名為 **my-function** 的函數上啟用主動追蹤。

```
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
```

追蹤模式是您發布函數版本時版本特定組態的一部分。您無法變更已發佈版本上的追蹤模式。

## 使用 啟用主動追蹤 CloudFormation
<a name="ruby-tracing-cloudformation"></a>

若要在 CloudFormation 範本中的 `AWS::Lambda::Function` 資源上啟用追蹤，請使用 `TracingConfig` 屬性。

**Example [function-inline.yml](https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/templates/function-inline.yml) - 追蹤組態**  

```
Resources:
  function:
    Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
    Properties:
      TracingConfig:
        Mode: Active
      ...
```

對於 AWS Serverless Application Model (AWS SAM) `AWS::Serverless::Function` 資源，請使用 `Tracing` 屬性。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-nodejs/template.yml) - 追蹤組態**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Tracing: Active
      ...
```

## 將執行時間相依性儲存在圖層中
<a name="ruby-tracing-layers"></a>

如果您使用 X-Ray 開發套件來檢測函數程式碼的 AWS SDK 用戶端，您的部署套件可能會變得相當大。為了避免每次更新函數程式碼時上傳執行時間相依性，請將 X-Ray SDK 封裝在一個 [Lambda 層](chapter-layers.md)中。

下面的例子顯示了儲存適用於 Ruby 的 X-Ray 開發套件的 `AWS::Serverless::LayerVersion` 資源。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby/template.yml) - 相依性層**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      CodeUri: function/.
      Tracing: Active
      Layers:
        - !Ref libs
      ...
  libs:
    Type: [AWS::Serverless::LayerVersion](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-layerversion.html)
    Properties:
      LayerName: blank-ruby-lib
      Description: Dependencies for the blank-ruby sample app.
      ContentUri: lib/.
      CompatibleRuntimes:
        - ruby2.5
```

透過此組態，您只有在變更執行時間相依性時才會更新程式庫層。由於函數部署套件僅含有您的程式碼，因此有助於減少上傳時間。

為相依性建立圖層需要建置變更，才能在部署之前產生圖層封存。如需工作範例，請參閱 [blank-ruby](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-ruby) 範例應用程式。