設定環境


您通常需要為函式進行額外設定,例如 第三方 API 金鑰或可調整設定Cloud Functions 專用的 Firebase SDK 提供 內建的環境設定,方便您輕鬆儲存和擷取 決定專案的資料類型

選項有以下三種:

  • 參數化設定 (適用於多數情況)。這能提供強型別的環境 含有會在部署期間驗證的參數 不但能防止錯誤,還能簡化偵錯作業。
  • 環境變數的檔案型設定。採用這個方法時,您必須手動建立 dotenv 檔案進行載入 環境變數
  • 使用 Firebase CLI 的執行階段環境設定functions.config (僅限 Cloud Functions (第 1 代))。

在大多數情況下,建議您採用參數化設定。這個方法 可讓您在執行階段和部署期間使用設定值。 除非所有參數具備有效的值,否則部署作業會遭到封鎖。 反之,在部署時無法使用環境變數的設定 讓應用程式從可以最快做出回應的位置 回應使用者要求

參數化設定

Cloud Functions for Firebase 提供定義設定的介面 並在程式碼集中宣告式參數這些參數的值是 在函式部署期間、設定部署和執行階段時 選項和執行期間也就是說,CLI 除非所有參數具備有效的值

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineInt, defineString } = require('firebase-functions/params');

// Define some parameters
const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")
WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

# To use configured parameters inside the config for a function, provide them
# directly. To use them at runtime, call .value() on them.
@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

部署含有參數化設定變數的函式時, Firebase CLI 會先嘗試從本機 .env 檔案載入值。如果他們 沒有出現在這些檔案中,且未設定 default,CLI 會提示: 將這些值自動儲存至 functions/ 目錄中名為 .env.<project_ID>.env 檔案:

$ firebase deploy
i  functions: preparing codebase default for deployment
? Enter a string value for ENVIRONMENT: prod
i  functions: Writing new parameter values to disk: .env.projectId
…
$ firebase deploy
i  functions: Loaded environment variables from .env.projectId

視開發工作流程而定,建議您將產生的 .env.<project_ID> 檔案新增至版本管控系統。

在全域範圍使用參數

部署期間,系統會在 每個參數都有實際值也就是說,在測試期間 全域範圍會導致部署失敗。如果您要使用 參數來初始化全域值,請使用初始化回呼 onInit()。此回呼會在實際執行任何函式之前執行, 沒有在部署期間呼叫,因此您可以透過安全的地方存取參數的 值。

Node.js

const { GoogleGenerativeAI } = require('@google/generative-ai');
const { defineSecret } = require('firebase-functions/params');
const { onInit } = require('firebase-functions/v2/core');

const apiKey = defineSecret('GOOGLE_API_KEY');

let genAI;
onInit(() => {
  genAI = new GoogleGenerativeAI(apiKey.value());
})

Python

from firebase_functions.core import init
from firebase_functions.params import StringParam, PROJECT_ID
import firebase_admin
import vertexai

location = StringParam("LOCATION")

x = "hello"

@init
def initialize():
  # Note: to write back to a global, you'll need to use the "global" keyword
  # to avoid creating a new local with the same name.
  global x
  x = "world"
  firebase_admin.initialize_app()
  vertexai.init(PROJECT_ID.value, location.value)

請注意,如果您使用 Secret 類型的參數,這類參數僅適用於 會在繫結密鑰的函式程序中執行。如果密鑰已繫結 僅在某些函式中,使用 secret.value() 前檢查 secret.value() 是否為偽陰性。

設定 CLI 行為

您可以使用用來控管 CLI 方式的 Options 物件來設定參數 會提示您輸入值下列範例將用來設定驗證 格式、提供簡易選項,以及 從 Firebase 專案中自動填入選取選項:

Node.js

const { defineString } = require('firebase-functions/params');

const welcomeMessage = defineString('WELCOME_MESSAGE', {default: 'Hello World',
description: 'The greeting that is returned to the caller of this function'});

const onlyPhoneNumbers = defineString('PHONE_NUMBER', {
  input: {
    text: {
      validationRegex: /\d{3}-\d{3}-\d{4}/,
      validationErrorMessage: "Please enter
a phone number in the format XXX-YYY-ZZZZ"
    },
  },
});

const selectedOption = defineString('PARITY', {input: params.select(["odd", "even"])});

const memory = defineInt("MEMORY", {
  description: "How much memory do you need?",
  input: params.select({ "micro": 256, "chonky": 2048 }),
});

const extensions = defineList("EXTENSIONS", {
  description: "Which file types should be processed?",
  input: params.multiSelect(["jpg", "tiff", "png", "webp"]),
});

const storageBucket = defineString('BUCKET', {
  description: "This will automatically
populate the selector field with the deploying Cloud Project’s
storage buckets",
  input: params.PICK_STORAGE_BUCKET,
});

Python

from firebase_functions.params import (
    StringParam,
    ListParam,
    TextInput,
    SelectInput,
    SelectOptions,
    ResourceInput,
    ResourceType,
)

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

WELCOME_MESSAGE = StringParam(
    "WELCOME_MESSAGE",
    default="Hello World",
    description="The greeting that is returned to the caller of this function",
)

ONLY_PHONE_NUMBERS = StringParam(
    "PHONE_NUMBER",
    input=TextInput(
        validation_regex="\d{3}-\d{3}-\d{4}",
        validation_error_message="Please enter a phone number in the format XXX-YYY-XXX",
    ),
)

SELECT_OPTION = StringParam(
    "PARITY",
    input=SelectInput([SelectOptions(value="odd"), SelectOptions(value="even")]),
)

STORAGE_BUCKET = StringParam(
    "BUCKET",
    input=ResourceInput(type=ResourceType.STORAGE_BUCKET),
    description="This will automatically populate the selector field with the deploying Cloud Project's storage buckets",
)

參數類型

參數化設定為參數值提供強大的輸入功能, 也支援 Cloud Secret Manager 的密鑰支援的類型如下:

  • 密鑰
  • 字串
  • 布林值
  • 整數
  • 浮點值
  • 清單 (Node.js)

參數值和運算式

Firebase 會在部署時間和函式執行時評估參數 正在執行由於這種雙重環境,當出現上述情況時, 比較參數值,以及使用該值設定應用程式的執行階段選項時 函式。

如要將參數做為執行階段選項傳遞至函式,請直接傳送參數:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineInt } = require('firebase-functions/params');
const minInstancesConfig = defineInt('HELLO\_WORLD\_MININSTANCES');

export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam

MIN_INSTANCES = IntParam("HELLO_WORLD_MIN_INSTANCES")

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

此外,如果需要與參數進行比較 您需要使用內建比較子,而不是 檢查值:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const environment = params.defineString(‘ENVIRONMENT’, {default: 'dev'});

// use built-in comparators
const minInstancesConfig = environment.equals('PRODUCTION').thenElse(10, 1);
export const helloWorld = onRequest(
  { minInstances: minInstancesConfig },
  (req, res) => {
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import IntParam, StringParam

ENVIRONMENT = StringParam("ENVIRONMENT", default="dev")
MIN_INSTANCES = ENVIRONMENT.equals("PRODUCTION").then(10, 0)

@https_fn.on_request(min_instances=MIN_INSTANCES)
def hello_world(req):
    ...

僅限在執行階段使用的參數和參數運算式可以 透過其 value 函式存取:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineString } = require('firebase-functions/params');
const welcomeMessage = defineString('WELCOME_MESSAGE');

// To use configured parameters inside the config for a function, provide them
// directly. To use them at runtime, call .value() on them.
export const helloWorld = onRequest(
(req, res) => {
    res.send(`${welcomeMessage.value()}! I am a function.`);
  }
);

Python

from firebase_functions import https_fn
from firebase_functions.params import StringParam

WELCOME_MESSAGE = StringParam("WELCOME_MESSAGE")

@https_fn.on_request()
def hello_world(req):
    return https_fn.Response(f'{WELCOME_MESSAGE.value()}! I am a function!')

內建參數

Cloud Functions SDK 提供三個預先定義的參數,可從 firebase-functions/params 子套件:

Node.js

  • projectID:執行函式的 Cloud 專案。
  • databaseURL:相關聯的即時資料庫執行個體網址 函式 (如果 Firebase 專案已啟用)
  • storageBucket:與函式相關聯的 Cloud Storage 值區 (如果 Firebase 專案已啟用)。

Python

  • PROJECT_ID:執行函式的 Cloud 專案。
  • DATABASE_URL:相關聯的即時資料庫執行個體網址 函式 (如果 Firebase 專案已啟用)
  • STORAGE_BUCKET:與函式相關聯的 Cloud Storage 值區 (如果 Firebase 專案已啟用)。

這些函式,就像使用者定義字串一樣 參數的值,但因為系統一律會知道這些參數的值 Firebase CLI 設定時,系統一律不會在部署作業時提示其值,也不會提出相關提示 已儲存到 .env 個檔案。

密鑰參數

使用 defineSecret() 定義的 Secret 類型參數代表字串 含有值儲存在 Cloud Secret Manager 的參數而不是 檢查本機 .env 檔案,如果 缺少密鑰參數檢查 Cloud Secret Manager 是否存在 要求提供新密鑰的值

以這種方式定義的密鑰參數必須繫結至個別函式, 應具備下列存取權:

Node.js

const { onRequest } = require('firebase-functions/v2/https');
const { defineSecret } = require('firebase-functions/params');
const discordApiKey = defineSecret('DISCORD_API_KEY');

export const postToDiscord = onRequest(
  { secrets: [discordApiKey] },
  (req, res) => {
  const apiKey = discordApiKey.value();
    //…

Python

from firebase_functions import https_fn
from firebase_functions.params import SecretParam

DISCORD_API_KEY = SecretParam('DISCORD_API_KEY')

@https_fn.on_request(secrets=[DISCORD_API_KEY])
def post_to_discord(req):
    api_key = DISCORD_API_KEY.value

由於密鑰值會一直隱藏,直到您執行函式為止,所以 也無法在設定函式時使用。

環境變數

Cloud Functions for Firebase 支援 dotenv.env 檔案中指定的環境變數載入 應用程式執行階段部署完成後,您可以透過 process.env敬上 介面 (以 Node.js 為基礎的專案) 或 os.environ (英吋 Python 型專案)。

如要以這種方式設定環境,請在專案中建立 .env 檔案。 新增所需變數,然後部署:

  1. functions/ 目錄中建立 .env 檔案:

    # Directory layout:
    #   my-project/
    #     firebase.json
    #     functions/
    #       .env
    #       package.json
    #       index.js
    
  2. 開啟 .env 檔案進行編輯,然後新增所需的金鑰。例如:

    PLANET=Earth
    AUDIENCE=Humans
    
  3. 部署函式並驗證環境變數是否已載入:

    firebase deploy --only functions
    # ...
    # i functions: Loaded environment variables from .env.
    # ...
    

部署完自訂變數之後 您的函式程式碼皆可存取:

Node.js

// Responds with "Hello Earth and Humans"
exports.hello = onRequest((request, response) => {
  response.send(`Hello ${process.env.PLANET} and ${process.env.AUDIENCE}`);
});

Python

import os

@https_fn.on_request()
def hello(req):
    return https_fn.Response(
        f"Hello {os.environ.get('PLANET')} and {os.environ.get('AUDIENCE')}"
    )

部署多組環境變數

如果 Firebase 需要一組替代環境變數 例如測試或正式環境 並寫入 .env.<project or alias> 檔案 專案專屬的環境變數環境變數中的環境變數 .env 與專案專屬的 .env 檔案 (如果有的話) 都會納入所有已部署的函式中

舉例來說,專案可以包含這三個檔案 開發和實際工作環境的不同值:

.env .env.dev .env.prod
PLANET=地球

AUDIENCE=人類

AUDIENCE=Dev Humans AUDIENCE=Prod Humans

考量這些個別檔案中的值,環境變數組合 會因目標專案而異:

$ firebase use dev
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.dev.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Dev Humans

$ firebase use prod
$ firebase deploy --only functions
i functions: Loaded environment variables from .env, .env.prod.
# Deploys functions with following user-defined environment variables:
#   PLANET=Earth
#   AUDIENCE=Prod Humans

預留的環境變數

部分環境變數金鑰僅限內部使用。請勿使用 下列金鑰:.env

  • 開頭為 X_GOOGLE_ 的所有金鑰
  • 從 EXT_ 開始的所有金鑰
  • 所有開頭為「FIREBASE_」的金鑰
  • 下列清單中的任何鍵:
  • CLOUD_RUNTIME_CONFIG
  • ENTRY_POINT
  • GCP 專案
  • GCLOUD_PROJECT
  • GOOGLE_CLOUD_PROJECT
  • FUNCTION_TRIGGER_TYPE
  • FUNCTION_NAME
  • FUNCTION_MEMORY_MB
  • FUNCTION_TIMEOUT_SEC
  • FUNCTION_IDENTITY
  • 區域
  • FUNCTION_TARGET
  • FUNCTION_SIGNATURE_TYPE
  • K_SERVICE
  • K_REVISION
  • 通訊埠
  • K_設定

儲存及存取機密設定資訊

儲存在 .env 檔案中的環境變數可用於函式 但我們不建議您以安全的方式儲存 例如資料庫憑證或 API 金鑰尤其是 因為將 .env 檔案簽入原始碼控管系統的情況下相當重要。

為協助您儲存敏感設定資訊,Cloud Functions for Firebase 與 Google Cloud 相互整合 Secret Manager。 這項加密服務會安全地儲存設定值 仍可視需要從您的函式中存取。

建立及使用密鑰

如要建立密鑰,請使用 Firebase CLI。

如何建立及使用密鑰:

  1. 在本機專案的根目錄中,執行下列指令:

    firebase functions:secrets:set SECRET_NAME

  2. 輸入 SECRET_NAME 的值。

    CLI 會回應成功訊息,並警告您必須部署函式 ,變更才會生效

  3. 部署之前,請先確認函式程式碼允許函式使用 runWith 參數存取密鑰:

    Node.js

    const { onRequest } = require('firebase-functions/v2/https');
    
    exports.processPayment = onRequest(
      { secrets: ["SECRET_NAME"] },
      (req, res) => {
        const myBillingService = initializeBillingService(
          // reference the secret value
          process.env.SECRET_NAME
        );
        // Process the payment
      }
    );

    Python

    import os
    from firebase_functions import https_fn
    
    @https_fn.on_request(secrets=["SECRET_NAME"])
    def process_payment(req):
        myBillingService = initialize_billing(key=os.environ.get('SECRET_NAME'))
        # Process the payment
        ...
    
  4. 部署 Cloud Functions:

    firebase deploy --only functions

    現在,您將能夠像其他環境變數一樣進行存取。 相反地,如果其他函式未在 runWith 嘗試存取密鑰,會收到未定義的值:

    Node.js

    exports.anotherEndpoint = onRequest((request, response) => {
      response.send(`The secret API key is ${process.env.SECRET_NAME}`);
      // responds with "The secret API key is undefined" because the `runWith` parameter is missing
    });
    

    Python

    @https_fn.on_request()
    def another_endpoint(req):
        return https_fn.Response(f"The secret API key is {os.environ.get("SECRET_NAME")}")
        # Responds with "The secret API key is None" because the `secrets` parameter is missing.
    

部署函式之後,這個函式即可存取密鑰值。只有 如果函式的 runWith 參數中明確包含密鑰,就會 並以環境變數的形式存取該密鑰這有助於確保 密鑰值只能在需要的位置使用,因此降低 就是不小心洩漏密鑰

管理密鑰

請使用 Firebase CLI 管理密鑰。透過這種方式管理密鑰時 請注意,部分 CLI 變更需要您修改和/或重新部署 以及相關功能具體步驟包括:

  • 每次設定密鑰的新值時,您都必須重新部署所有 參照的函式 以便他們取得最新的值
  • 如果您刪除密鑰,請確認沒有任何部署的函式 參照該密鑰使用以下項目的密鑰值: 刪除作業就會失敗,且不會顯示相關通知。

以下摘要說明適用於密鑰管理的 Firebase CLI 指令:

# Change the value of an existing secret
firebase functions:secrets:set SECRET_NAME

# View the value of a secret
functions:secrets:access SECRET_NAME

# Destroy a secret
functions:secrets:destroy SECRET_NAME

# View all secret versions and their state
functions:secrets:get SECRET_NAME

# Automatically clean up all secrets that aren't referenced by any of your functions
functions:secrets:prune

對於 accessdestroy 指令,您可以提供選用版本 參數來管理特定版本。例如:

functions:secrets:access SECRET_NAME[@VERSION]

如要進一步瞭解這些作業,請透過下列指令將 -h 傳送至 查看 CLI 說明

密鑰的計費方式

Secret Manager 允許使用 6 個有效的密鑰 版本 這代表您在 Firebase 中每個月可以有 6 組密鑰 免費專案

根據預設,Firebase CLI 會自動刪除未使用的密鑰 或是適當版本;例如使用新版本部署函式時 密鑰此外,您可以使用以下指令主動清除未使用的密鑰 《functions:secrets:destroy》和《functions:secrets:prune》。

Secret Manager 每月有超過 10,000 次存取作業 密鑰。函式執行個體只會讀取 runWith 中指定的密鑰 參數值。如有大量函式執行個體 專案可能會超過此限額 每 10,000 次存取作業,您須支付 $0.03 美元。

若需更多資訊,請參閲 Secret Manager 定價

模擬器支援

此環境設定可與 dotenv 互通, 本機 Cloud Functions 模擬器

使用本機 Cloud Functions 模擬器時,您可以覆寫環境 設定 .env.local 檔案來建立專案的變數。內容 .env.local 的優先順序高於 .env 和專案專屬 .env 檔案。

舉例來說,專案可以包含這三個檔案 開發和本機測試的不同值:

.env .env.dev .env.local
PLANET=地球

AUDIENCE=人類

AUDIENCE=Dev Humans AUDIENCE=當地人

在本機環境中啟動時,模擬器會載入環境 變數,如下所示:

  $ firebase emulators:start
  i  emulators: Starting emulators: functions
  # Starts emulator with following environment variables:
  #  PLANET=Earth
  #  AUDIENCE=Local Humans

Cloud Functions 模擬器中的密鑰和憑證

Cloud Functions 模擬器支援使用密鑰來 儲存及存取機密設定資訊。 根據預設,模擬器會嘗試使用 應用程式預設憑證。 模擬器在某些情況下 (例如 CI 環境) 可能會無法存取 存取所有 Secret 值。

與 Cloud Functions 模擬器對環境變數的支援類似,您可以 設定 .secret.local 檔案來覆寫密鑰值。如此一來 方便您在本機測試函式 (尤其是沒有存取權限的情況下) 設為密鑰值。

從環境設定遷移

如果您已透過 functions.config 使用環境設定, 可以遷移現有設定做為環境變數 (位於 dotenv 格式。 Firebase CLI 提供匯出指令,藉此輸出設定 您目錄的 .firebaserc 檔案中所列的每個別名或專案 (在以下範例中,localdevprod) 做為 .env 檔案。

如要遷移,請使用 firebase functions:config:export 指令:

firebase functions:config:export
i  Importing configs from projects: [project-0, project-1]
⚠  The following configs keys could not be exported as environment variables:

⚠  project-0 (dev):
    1foo.a => 1FOO\_A (Key 1FOO\_A must start with an uppercase ASCII letter or underscore, and then consist of uppercase ASCII letters, digits, and underscores.)

Enter a PREFIX to rename invalid environment variable keys: CONFIG\_
✔  Wrote functions/.env.prod
✔  Wrote functions/.env.dev
✔  Wrote functions/.env.local
✔  Wrote functions/.env

請注意,在某些情況下,系統會提示您輸入要重新命名的前置字串 匯出的環境變數金鑰這是因為並非所有設定 可能無效,或可能是 預留環境變數金鑰

建議您仔細檢查系統產生的 .env 檔案內容 再部署函式或檢查 .env 檔案到原始碼控管系統中。如果 所有值都屬於敏感資訊,不應外洩,請從 .env 中移除 將檔案安全地儲存在 Secret Manager

此外,您也需要更新函式程式碼。任何使用 functions.config 現在必須改用 process.env,如 環境變數