创建Custom Container函数

当函数计算平台的标准运行时无法满足您的业务需求时,可以选择自定义容器函数。本文介绍如何在函数计算控制台或使用Serverless Devs工具创建Custom Container函数。

注意事项

  • 在函数计算中,创建Custom Container函数必须使用同一账号下相同地域内阿里云镜像服务仓库中的镜像。针对搭载Apple芯片的Mac电脑(或其他ARM架构的机器),构建镜像时需要指定镜像的编译平台为Linux/Amd64,示例命令如docker build --platform linux/amd64 -t $IMAGE_NAME .

  • 函数计算在解析ACR企业版镜像域名时,使用镜像仓库实例配置的专有网络默认解析或云解析PrivateZone自动解析的访问IP地址。具体场景如下:

    • 场景一:如果ACR企业版实例的访问控制页面的访问 IP中不存在默认解析标识时,该列表下的所有IP地址均为云解析PrivateZone自动解析的IP地址,任意一个VPC配置均可使用。

      image

    • 场景二:如果ACR企业版实例的访问控制页面的访问 IP中存在默认解析标识的IP地址为专有网络默认解析的IP地址,以下图为例,只能选择第一个VPC。

      image

  • 使用企业版实例时只能选择非加速镜像,并且每次更新函数的镜像配置时,都会基于最新选择的原始镜像生成最新的加速镜像(如果加速镜像已存在会覆盖生成)。请不要删除原始镜像以及加速镜像,否则会影响函数调用。

  • 请确保您在函数配置中的镜像在发生任何变化后,及时更新您的函数,否则函数调用会失败。

    • 请确保原始镜像存在,否则函数会进入Failed状态,并且无法调用。函数计算虽然对您的函数做了缓存以加速冷启动速度,但是在调用过程中依然依赖您的原始镜像的存在。

    • 请确保您在任何函数中使用的镜像不要被覆盖,如果被覆盖为其他的Digest,请及时使用最新的镜像信息重新部署您的函数。函数计算会同时记录您在创建和更新配置时所选择的镜像版本Tag和Digest,如果您的镜像版本在别的地方被更新为其他的Digest,函数将调用失败。

前提条件

在控制台创建函数

  1. 登录函数计算控制台,在左侧导航栏,单击函数

  2. 在顶部菜单栏,选择地域,然后在函数页面,单击创建函数

  3. 创建函数页面,选择使用容器镜像方式,按需设置以下配置项,然后单击创建

    • 基本设置:设置函数名称。

    • 镜像配置:配置创建函数的镜像。

      配置项

      说明

      镜像选择方式

      您可以使用示例镜像或者您自己的镜像创建函数。

      • 使用示例镜像:选择函数计算自带的示例镜像。

      • 使用 ACR 中的镜像:单击配置项容器镜像下方的选择 ACR 中的镜像,在弹出的选择容器镜像面板,选择已创建的容器镜像实例ACR 镜像仓库,然后在下方选择镜像区域找到目标镜像并在其右侧操作列单击选择

        说明
        • 不支持使用跨账户ACR中的公开镜像创建函数。

        • 请确保您在函数配置中的镜像在发生任何变化后,及时更新您的函数,否则函数调用会失败。具体请参见注意事项

        • 使用企业版实例时,只能选择非加速镜像,请不要删除原始镜像以及加速镜像,否则会影响函数调用。具体请参见注意事项

        • 使用企业版实例时,不支持自定义域名格式的镜像地址。

      启动命令

      容器的启动命令。如果不填写,则默认使用镜像中的Entrypoint或者CMD。

      监听端口

      容器镜像中的HTTP Server所监听的端口。默认端口为9000。

    • 高级配置:配置函数的实例相关信息、执行超时时间和网络设置等。

      配置项

      说明

      是否使用GPU

      根据您的业务情况,选择是否使用GPU实例。默认使用弹性实例,不使用GPU实例。更多信息,请参见实例类型及使用模式。关于各种实例类型的计费详情,请参见计费概述

      • 使用GPU

      • 不使用GPU

      规格方案

      • 选择使用GPU

        根据您的业务情况,选择合理的GPU规格函数计算将根据您选择的GPU规格自动选定vCPU规格内存规格,不支持灵活配比。

      • 选择不使用GPU

        根据您的业务情况,选择或手动输入合理的vCPU规格内存规格组合。

      关于各资源使用的计费详情,请参见计费概述

      说明

      vCPU大小(单位为核)与内存大小(单位为GB)的比例必须设置在1∶1到1∶4之间。

      临时硬盘大小

      根据您的业务情况,选择硬盘大小。函数计算为您提供512 MB以内的磁盘免费使用额度。更多信息,请参见计费概述

      执行超时时间

      设置超时时间。默认为60秒,最长为86400秒,推荐您设置为600秒。

      说明

      超过设置的超时时间,函数将以执行失败结束。如需更长的超时时间限制,请加入钉钉用户群(钉钉群号64970014484)申请。

      单实例并发度

      设置函数实例的并发度。具体信息,请参见设置实例并发度

      时区

      选择函数的时区。此处设置函数的时区后,将自动为函数添加一条环境变量TZ,其值为您设置的目标时区。

      函数角色

      如果您的代码逻辑需访问其他云服务,请创建角色并为角色最小化授予访问其他云服务的权限。更多信息,请参见授予函数计算访问其他云服务的权限

      允许访问 VPC

      是否允许函数访问VPC内资源。更多信息,请参见配置网络

      专有网络

      允许访问 VPC选择时必填。创建新的VPC或在下拉列表中选择要访问的VPC ID。

      交换机

      允许访问 VPC选择时必填。创建新的交换机或在下拉列表中选择交换机ID。

      安全组

      允许访问 VPC选择时必填。创建新的安全组或在下拉列表中选择安全组。

      允许函数默认网卡访问公网

      是否允许函数可以通过默认网卡访问公网。关闭后,当前函数将无法通过函数计算的默认网卡访问公网。

      重要

      使用固定公网IP地址功能时,您必须关闭允许函数默认网卡访问公网,否则配置的固定公网IP地址不生效。更多信息,请参见配置固定公网IP地址

      日志功能

      是否启用日志功能,取值说明如下:

      • 启用:启用后,您可以查看函数的调用日志,函数的调用日志将通过日志服务存储和查询。

      • 禁用:不启用日志功能。

    • 环境变量:设置函数运行环境中的环境变量。更多信息,请参见配置环境变量

    创建完成后,您可以在函数列表中查看和更新已创建的函数。

说明

更新函数时,只能变更已设置的监听端口,不能删除或添加额外的监听端口。如果创建函数时,配置了监听端口,更新该函数时,不指定监听端口,将保留创建函数时的监听端口。

使用Serverless Devs创建函数

使用Serverless Devs可以一键构建、推送容器镜像并部署函数。

  1. 执行以下命令,初始化项目。

    sudo s init

    根据界面提示,依次选择阿里云账号、Custom Container模板和具体的语言(本文以Node.js为例),设置工程名称、选择项目部署地域并输入您的ACR镜像等。

    image

  2. 执行以下命令,进入项目目录。

    cd start-fc3-custom-container-nodejs
  3. 编辑s.yaml文件。关于YAML文件的参数解释,请参见YAML规范

    示例如下。

    示例中image为您的ACR镜像,需要分别将<your namespace>、<your image>和<your tag>替换为实际的命名空间名称、镜像仓库名称和镜像版本。如果您在步骤1初始化项目时已填入正确的ACR镜像,此处无需修改。

    edition: 3.0.0
    name: hello-world-app
    # access 是当前应用所需要的密钥信息配置:
    # 密钥配置可以参考:https://www.serverless-devs.com/serverless-devs/command/config
    # 密钥使用顺序可以参考:https://www.serverless-devs.com/serverless-devs/tool#密钥使用顺序与规范
    access: "default"
    
    vars: # 全局变量
      region: "cn-hangzhou"
    
    resources:
      hello_world:
        # 如果只想针对 hello_world 下面的业务进行相关操作,可以在命令行中加上 hello_world,例如:
        # 只对 hello_world 进行构建:s hello_world build
        # 如果不带有 hello_world ,而是直接执行 s build,工具则会对当前Yaml下,所有和 hello_world 平级的业务模块(如有其他平级的模块,例如下面注释的next_function),按照一定顺序进行 build 操作
        component: fc3 # 组件名称
        actions:       # 自定义执行逻辑
          pre-deploy: # 在deploy之前运行
            - component: fc3 build --dockerfile ./code/Dockerfile  # 要运行的组件,格式为“component: 组件名 命令 参数”
        props:
          region: ${vars.region}              # 关于变量的使用方法,可以参考:https://docs.serverless-devs.com/serverless-devs/yaml#%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC
          functionName: "start-nodejs-ufrz"
          runtime: "custom-container"
          description: 'hello world by serverless devs'
          timeout: 30
          memorySize: 512
          cpu: 0.5
          diskSize: 512
          code: ./code
          customContainerConfig:
            image: 'registry.${vars.region}.aliyuncs.com/<your namespace>/<your image>:<your tag>'  # 您的ACR镜像,需要分别将<your namespace>、<your image>和<your tag>替换为实际的命名空间名称、镜像仓库名称和镜像版本
          # triggers:
          #   - triggerName: httpTrigger # 触发器名称
          #     triggerType: http # 触发器类型
          #     description: 'xxxx'
          #     qualifier: LATEST # 触发服务的版本
          #     triggerConfig:
          #       authType: anonymous # 鉴权类型,可选值:anonymous、function
          #       disableURLInternet: false # 是否禁用公网访问 URL
          #       methods: # HTTP 触发器支持的访问方法,可选值:GET、POST、PUT、DELETE、HEAD
          #         - GET
          #         - POST
  4. 执行以下命令,部署项目。

    sudo s deploy

    输出示例:

      Steps for [deploy] of [hello-world-app]
    ====================
    
    DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
                BuildKit is currently disabled; enable it by removing the DOCKER_BUILDKIT=0
                environment-variable.
    
    Sending build context to Docker daemon   5.12kB
    Step 1/7 : FROM node:14-buster
    14-buster: Pulling from library/node
    2ff1d7c41c74: Already exists 
    b253aeafeaa7: Already exists 
    3d2201bd995c: Already exists 
    1de76e268b10: Already exists 
    d9a8df589451: Already exists 
    6f51ee005dea: Already exists 
    5f32ed3c3f27: Already exists 
    0c8cc2f24a4d: Already exists 
    0d27a8e86132: Already exists 
    Digest: sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6fd8461aa
    Status: Downloaded newer image for node:14-buster
     ---> 1d12470fa662
    Step 2/7 : WORKDIR /usr/src/
     ---> Running in 70a8e2e4d1ea
    Removing intermediate container 70a8e2e4d1ea
     ---> 0d67b8fa2901
    Step 3/7 : COPY package*.json ./
     ---> 09eb15f8770a
    Step 4/7 : RUN npm install
     ---> Running in 8ae492be973b
    Step 5/7 : COPY . .
     ---> 7560c7b14431
    Step 6/7 : EXPOSE 9000
     ---> Running in 66b38e54ced0
    Removing intermediate container 66b38e54ced0
     ---> f73cce48d2ae
    Step 7/7 : ENTRYPOINT [ "node", "server.js" ]
     ---> Running in 2fb2f83fd6c0
    Removing intermediate container 2fb2f83fd6c0
     ---> fe51ae71448c
    Successfully built fe51ae71448c
    Successfully tagged registry.cn-hangzhou.aliyuncs.com/z****/z****:latest
    
    [2024-01-29 16:33:06][INFO][hello_world] get instanceName= and region=cn-hangzhou from registry.cn-hangzhou.aliyuncs.com/z****/z****
    [2024-01-29 16:33:06][INFO][hello_world] try to docker push registry.cn-hangzhou.aliyuncs.com/z****/z**** ...
    
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
    
    Using default tag: latest
    The push refers to repository [registry.cn-hangzhou.aliyuncs.com/z****/z****]
    85c1ec915b45: Pushed 
    37c36543a431: Pushed 
    e4afd7f70434: Pushed 
    0d5f5a015e5d: Layer already exists 
    3c777d951de2: Layer already exists 
    f8a91dd5fc84: Layer already exists 
    cb81227abde5: Layer already exists 
    e01a454893a9: Layer already exists 
    c45660adde37: Layer already exists 
    fe0fb3ab4a0f: Layer already exists 
    f1186e5061f2: Layer already exists 
    b2dba7477754: Layer already exists 
    latest: digest: sha256:6bf1ed4119d197a46c99082577632957056cb625f2ee0276d2af53f60d22837d size: 2841
    
    
    
      [hello_world] completed (688.45s)
    
      Result for [deploy] of [hello-world-app]
    ====================
    region:                cn-hangzhou
    cpu:                   0.5
    customContainerConfig: 
      image:            registry.cn-hangzhou.aliyuncs.com/z****/z****
      resolvedImageUri: registry.cn-hangzhou.aliyuncs.com/z****/z****@sha256:6bf1ed4119d197a46c99082577632957056cb625f2ee0276d2af53f60d22837d
    description:           hello world by serverless devs
    diskSize:              512
    functionName:          start-nodejs-ufrz
    handler:               handler
    instanceConcurrency:   1
    internetAccess:        true
    lastUpdateStatus:      Successful
    memorySize:            512
    role:                  
    runtime:               custom-container
    state:                 Active
    timeout:               30
    
    A complete log of this run can be found in: /root/.s/logs/0129162246
  5. 执行以下命令,调试函数。

    sudo s invoke -e "{\"key\":\"val\"}"

    输出示例:

     Steps for [invoke] of [hello-world-app]
    ====================
    ========= FC invoke Logs begin =========
    FC Invoke Start RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    FC Invoke Start RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    hello world!
    
    FC Invoke End RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    
    Duration: 42.27 ms, Billed Duration: 43 ms, Memory Size: 512 MB, Max Memory Used: 47.77 MB
    ========= FC invoke Logs end =========
    
    Invoke instanceId: c-65b764db-15fa2aa8-bc50f7839399
    Code Checksum: undefined
    Qualifier: LATEST
    RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    
    Invoke Result:
    OK
      [hello_world] completed (4.96s)
    
    A complete log of this run can be found in: /root/.s/logs/0129164202

相关文档

  • 如果您要使用GPU实例,则只能创建Custom Container函数。关于GPU实例规格的选择,请参见创建Web函数

  • 使用Custom Container函数,容器镜像依赖的基础环境会带来额外的数据下载和解压的时间,为了降低冷启动时间,请参见函数计算冷启动优化最佳实践

  • 您也可以调用API来创建函数,更多信息,请参见CreateFunction - 创建函数

  • 关于函数计算提供的内置运行时、自定义运行时和自定义容器运行时适用场景及差异,请参见函数运行时选型