自定义镜像简介

本文介绍自定义镜像的背景信息、基本原理、使用限制和HTTP Server配置要求等。

背景信息

在云原生时代,容器镜像已经逐渐成为软件部署和开发的标准工具。为优化开发者体验、提升开发和交付效率,函数计算提供自定义镜像,开发者可以将容器镜像作为函数的交付物。使用自定义镜像具有以下优势。

  • 低成本迁移,无需修改代码或重新编译二进制文件。共享对象(*.so),保持开发和线上环境一致。

  • 避免代码和依赖分离,简化分发和部署的步骤。

  • 容器镜像天然分层缓存,提高代码上传和拉取效率。

  • 标准可复用的第三方库引用、分享、构建、代码上传、存储和版本管理,丰富的开源生态CI/CD交付体验。

  • 可通过HTTP协议和函数计算系统交互。

  • 可运行无需交互的镜像。

基本原理

函数计算系统初始化执行环境实例前会扮演该函数的服务角色(Service Role),获得临时用户名和密码并拉取镜像。拉取成功后,根据指定的启动命令Command和参数Args启动您的镜像。

容器镜像交付物需要包含HTTP Server。函数计算通过配置的CAPort端口监听您定义的HTTP Server,此HTTP Server将接管函数计算的所有请求,包括通过API调用和通过HTTP调用的请求。您在开发函数具体的交互逻辑之前,一般需要确认开发的是通过API调用函数还是通过HTTP请求调用函数,原理如下所示:

  • 通过API调用函数buhuo1containercustom1

  • 通过HTTP请求调用函数nuhuo2customcintainer2

使用限制

镜像大小限制

ACR个人版、企业版基础版、企业版标准版和高级版,CPU实例最大支持10 GB的未解压镜像,GPU实例最大支持15 GB的未解压镜像。

镜像仓库

支持拉取阿里云容器镜像服务的企业版和个人版镜像以及您自己搭建的私有镜像仓库的镜像。

镜像访问

目前仅ACR个人版公开镜像支持跨账号同地域读取,其余镜像仅支持同账号同地域下私有镜像仓库读取。

容器内文件读写权限

容器run-as-user UID默认是Root用户ID,即UID=0。如果您在Dockerfile中指定了具体的使用者,则会以指定的使用者运行该容器镜像。

容器可写层存储空间限制

排除只读镜像层,容器产生的数据大小限制为512 MB或10 GB,同函数高级配置项中的磁盘大小。具体信息,请参见创建函数

说明

容器可写层数据不是持久化的,数据会随着容器被销毁而删除。如果需要持久化存储,可以考虑使用函数计算挂载NAS或者OSS。具体操作,请参见配置NAS文件系统配置OSS对象存储。或者使用其他共享存储服务,例如表格存储等。

镜像架构限制

目前函数计算仅支持AMD64镜像架构,因此,针对搭载Apple芯片的Mac电脑(或其他ARM架构的机器),构建镜像时需要指定镜像的编译平台为Linux/Amd64。参考命令如docker build --platform linux/amd64 -t $IMAGE_NAME .

说明

构建完成后,可执行docker inspect进行检查。如果返回内容包含 "Architecture" : "amd64",则表示构建的镜像正确。

HTTP Server配置要求

以下要求仅适用于Web Server模式的自定义镜像函数:

  • 自定义镜像启动的服务一定要监听0.0.0.0:CAPort*:CAPort端口。如果您使用127.0.0.1:CAPort端口,会导致请求超时,出现以下错误:

    {
        "ErrorCode":"FunctionNotStarted",
        "ErrorMessage":"TheCA'shttpservercannotbestarted:ContainerStartDuration:25000000000.PingCAfaileddueto:dialtcp21.0.XX.XX:9000:getsockopt:connectionrefusedLogs:2019-11-29T09:53:30.859837462ZListeningonport9000"
    }

    自定义镜像的监听端口,即函数属性CAPort默认是9000。如果自定义镜像使用默认的监听端口,那么实现的自定义镜像的HTTP Server监听的端口也必须是9000。 如果自定义镜像使用的监听端口是8080,那么实现的自定义镜像的HTTP Server监听的端口也必须是8080。

  • Connection需要设置为Keep-Alive,Server端请求超时时间需设置在15分钟及以上。示例如下:

    //例如,Node.js使用Express时。  
    var server = app.listen(PORT, HOST);
    server.timeout = 0; // never timeout
    server.keepAliveTimeout = 0; // keepalive, never timeout
  • HTTP Server需要在120秒内启动完毕。

公共请求头

自定义镜像的公共请求头和自定义运行时的公共请求头一致。更多信息,请参见函数计算公共请求头

日志格式

自定义镜像中所有打印到标准输出(Stdout)的日志会自动收集到您指定的日志服务中。关于配置日志功能的具体操作,请参见配置日志

自定义镜像的日志格式与自定义运行时的日志格式一致。更多信息,请参见函数日志格式

冷启动优化最佳实践

相比于代码包,容器镜像依赖的基础环境会带来额外的数据下载和解压的时间。为了更好的冷启动体验,推荐您使用以下最佳实践:

  • 容器镜像地址推荐使用与函数计算同地域的VPC镜像地址,以减少镜像拉取延时,提高稳定性。

  • 镜像最小化,基于类似Alpine或Ubuntu这样的最小镜像或者是其他镜像的精简版本构建自定义镜像。仅保留必要的依赖,删除不必要的文档、数据和其他文件。

  • 容器镜像配合预留实例一起使用。更多信息,请参见配置预留实例

  • 在资源允许和线程安全的情况下,搭配使用单实例多并发功能,可避免不必要的冷启动,同时降低成本。更多信息,请参见创建Web函数

计费说明

自定义镜像的计费项与其他类型运行时的计费项一致。更多信息,请参见计费概述

其中,镜像资源使用量中的执行时间是从仓库拉取镜像到拉取镜像结束的时长。例如,1024 MB内存的实例拉取镜像耗时10秒,则本次拉取镜像的资源消耗量为10 GB*秒

容器镜像在一定时间范围内有缓存,因此并不是每次冷启动一定会产生镜像拉取的费用。

相关文档