使用自定义镜像部署模型服务

更新时间:
复制 MD 格式

EAS提供的官方镜像无法满足特定业务或环境需求时,可通过自定义镜像来封装完整的运行环境,实现灵活、可靠的模型服务部署。

镜像仓库规划

EAS部署服务时需要从镜像仓库拉取镜像,推荐使用阿里云容器镜像服务ACR存储镜像。拉取镜像时使用VPC地址,以获得更好的性能和安全性。

重要

公网拉取镜像存在安全风险,且速度会特别慢,不建议使用。

ACR个人版

  • 免费提供,但只能在一个地域内开通使用,跨地域拉取镜像只能通过公网地址。

  • 建议仅在测试场景使用ACR个人版,并确保与EAS服务同地域。

ACR企业版

  • 提供更强的安全、性能和全球同步能力,可实现EAS服务在同一地域或跨地域通过内网安全、高速地拉取镜像。

  • 推荐在生产环境中使用。

自建镜像仓库

  • 如果在阿里云VPC中使用Harbor自建镜像仓库,地址仅支持在VPC中访问,与ACR企业版类似,需要为EAS服务配置VPC,让镜像仓库与EAS服务处于同一VPC中。

镜像仓库身份认证

使用需要认证的私有镜像仓库,需在服务部署时提供用户名密码信息。

JSON配置文件中通过dockerAuth参数指定认证信息,值为username:passwordBase64编码形式。

例如,对于abcd:abcde12345,执行命令echo -n "abcd:abcde12345" | base64得到YWJjZDphYmNkZTEy****,即为dockerAuth的取值。

{"dockerAuth": "YWJjZDphYmNkZTEy****"}
说明

使用同一阿里云账号下同地域的ACR镜像仓库时,EAS免密拉取镜像,无需填写用户名密码。

快速开始:制作并部署自定义镜像

本节在阿里云ECS实例上构建一个基于GunicornFlaskWeb服务镜像,推送至ACR镜像仓库,并部署为EAS在线服务。

步骤一:环境准备

在开始之前,请确保已准备好以下环境和资源:

  • 专有网络 (VPC):EAS服务、ECS实例与ACR镜像仓库通过VPC通信,确保镜像推送拉取的稳定性和安全性。

  • 容器镜像仓库 (ACR):用于存储和管理自定义镜像。参见使用企业版实例推送和拉取镜像准备一个ACR企业版实例,并创建好所需的命名空间和镜像仓库。

  • 开发环境:创建一个配置如下的ECS实例来制作镜像。

    • 实例规格:ecs.u1-c1m2.large

    • 镜像:Alibaba Cloud Linux 3.2104 LTS 64

    • 扩展程序:Docker社区版

    • 网络:选择的VPC需在ACR企业版实例的”访问控制”中添加,否则无法推送镜像到ACR镜像仓库。详情请参见为ACR配置专有网络的访问控制

    说明

    也可以使用本地或其他开发环境。

    • 本地开发环境:安装并运行 Docker,用于在本地构建镜像。

    • 使用DSW开发环境:在DSW实例的操作列中单击制作镜像,系统将构建Docker镜像并保存到阿里云容器镜像服务ACR中,部署时选择自定义镜像即可下拉选择。详情请参见制作DSW实例镜像

步骤二:准备应用文件

创建一个项目文件夹(例如 my-app),并包含以下三个文件:

  1. requirements.txt (应用依赖)

    flask
    gunicorn
  2. app.py(Web应用代码)

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/hello/model')
    def hello_world():
        # 此处可以集成您的模型推理或其他业务逻辑
        return 'Hello World from Gunicorn!'
    
    # 注意:无需 app.run(),应用将由 Gunicorn 启动
  1. Dockerfile(镜像构建指令) 

    # 1. 使用轻量级的官方Python镜像作为基础
    FROM python:3.9-slim
    
    # 2. 设置工作目录
    WORKDIR /app
    
    # 3. 复制依赖文件并安装,利用Docker缓存机制加速后续构建
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
    
    # 4. 复制应用代码
    COPY app.py .
    
    # 5. 声明服务端口
    EXPOSE 8000
    
    # 6. 定义容器默认启动命令(可被EAS控制台的“运行命令”覆盖)
    CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]

步骤三:构建并推送镜像

  1. 打开终端,进入项目文件夹(my-app)。

  2. 登录到您的ACR实例。将命令中的占位符替换为实际信息。

    # 示例: docker login --username=your_user my-registry.cn-hangzhou.aliyuncs.com
    docker login --username=<用户名> <ACR仓库域名>
  3. 构建Docker镜像并为其打上完整的标签。

    # 示例: docker build -t my-registry.cn-hangzhou.aliyuncs.com/my-namespace/flask-app:v1 .
    docker build -t <ACR仓库域名>/<命名空间>/<镜像仓库名>:<版本号> .
  4. (推荐)推送前本地验证镜像:将镜像推送到 ACR 之前,建议先在本地运行以下命令验证镜像启动是否正常,避免将问题镜像推送至仓库。

    # 将 <端口号> 替换为 Dockerfile 中 EXPOSE 的端口(本示例为 8000)
    docker run -p <端口号>:<端口号> <ACR仓库域名>/<命名空间>/<镜像仓库名>:<版本号>

    若应用正常响应,则说明镜像可用,可继续推送。

  5. 将构建好的镜像推送到ACR。

    # 示例: docker push registry.cn-hangzhou.aliyuncs.com/my-namespace/flask-app:v1
    docker push <ACR仓库域名>/<命名空间>/<镜像仓库名>:<版本号>

步骤四:部署服务

  1. 登录PAI控制台,在页面上方选择目标地域,并在右侧选择目标工作空间,然后单击进入EAS

  2. 单击部署服务,选择自定义模型部署 > 自定义部署

  3. 配置以下关键参数:

    • 部署方式选择镜像部署

    • 镜像配置选择镜像地址,填写上一步中推送的完整镜像地址。

      由于本示例使用同一阿里云账号下的ACR,EAS可免密拉取镜像,无需提供用户名和密码。
    • 运行命令gunicorn -w 4 -b 0.0.0.0:8000 app:app

      逻辑说明:EAS控制台填写的运行命令覆盖 Dockerfile中的CMD指令。建议将启动命令填写在此处,便于后续调试和修改。
    • 端口号8000。

    • 部署资源:本示例使用CPU资源即可。如选择公共资源下的ecs.c6.large

    • 专有网络配置:选择一个VPC、交换机和安全组。

      请确保此处选择的VPC已在ACR实例的“访问控制”中添加,否则将因网络不通导致镜像拉取失败(常见错误为ImagePullBackOff)。
  4. 单击部署,当服务状态变为运行中,表示部署成功。

说明

修改镜像地址或更新服务配置:服务详情页展示的 JSON 配置为只读状态,无法直接编辑。如需修改,请通过服务列表中的更新入口操作。

步骤五:服务测试

服务部署成功后,获取访问地址和Token,使用以下命令测试Flask服务:

# <endpoint>和<token>替换为服务的实际调用地址和Token
curl <endpoint>/hello/model -H "Authorization: <token>"

如果返回 Hello World from Gunicorn!,则表示服务已成功部署并可正常访问。

关于服务调用的更多信息,请参见服务调用方式

核心概念与限制

  • 网络限制:EAS 服务通过VPC地址访问内网资源,通常需要配置VPC。如果需要访问公网资源(例如,使用 pip 从公共源安装依赖、调用外部 API 或通过公网拉取镜像),还需为VPC配置NAT网关。详情请参见EAS访问公网或内网资源

    成本提示:NAT网关是付费服务,会产生额外费用。
  • 端口限制

    • EAS服务引擎会占用 8080 和 9090 端口。您的应用程序监听的端口必须避开这两个端口,否则服务将因端口冲突启动失败。

    • 当服务包含多个容器时,各容器监听的端口还必须互不相同。例如,若主容器使用8000 端口,Sidecar 容器也不能使用8000 端口,否则将因端口冲突导致服务启动失败。

  • CUDA 版本:在线服务的 CUDA 版本由所选机型和基础镜像共同决定,无法在运行中直接更改。如需切换 CUDA 版本,须重新部署服务,并在部署时选择支持目标 CUDA 版本的镜像或机型。

  • Sidecar注入:为实现认证、鉴权和监控,EASSidecar模式在服务实例中注入一个代理容器。这个代理是透明的,但会占用少量资源,并负责将外部请求安全地转发到您配置的服务端口。

  • API协议支持:镜像部署支持在镜像中以HTTP、WebSocket、gRPC(HTTP2)三种协议提供API服务。

生产应用建议

  • 镜像与模型分离:始终将代码和模型文件分离。代码打包进镜像,模型存放在对象存储 OSS文件存储NAS上,在EAS部署页面通过存储挂载功能将模型挂载到容器内使用。这能缩短服务更新和扩容时的镜像拉取时间。

  • 使用内网拉取镜像:为安全和性能,务必为服务配置专有网络,使其能通过 VPC 地址从 ACR 拉取镜像

  • 预装依赖以优化启动速度:若服务每次重启都需要重新下载 Python 依赖包或大体积模型文件,会显著增加冷启动时间。建议在制作镜像时将 Python 环境、依赖包(如 PyTorch、Transformers 等框架)及模型文件直接预装到镜像中,确保容器启动后立即提供服务,避免运行时动态下载。

  • 注册镜像为AI资产:如果自定义的镜像可在其他多种场景下应用,可使用PAI AI资产的镜像功能,将其沉淀为AI资产统一管理。

  • 配置健康检查:为服务配置健康检查,EAS 会据此自动重启不健康的实例,保障服务稳定性。详情请参见健康检查

  • 启用自动扩缩容:当业务负载有明显波动时,开启水平自动扩缩容功能,以弹性、经济的方式应对流量变化。

常见问题

Q:镜像拉取失败(ImagePullBackOff)

请依次排查:

  1. 镜像地址正确性:请检查镜像地址、命名空间和版本号(Tag)是否正确,且镜像已成功推送到仓库。

  2. 系统盘空间:如有报错no space left on device,请扩容系统盘

  3. 网络连通性

    • 使用镜像公网地址:请确认已为EAS配置能访问公网的VPC,且为ACR开通公网访问(跨地域使用公网地址速度特别慢,容易因网络问题失败)。

    • 使用镜像内网地址:如果跨地域,仅支持使用ACR企业版,且需打通VPC。详情请参见跨地域或从IDC访问ACR企业版实例

  4. ACR访问控制:根据使用的镜像地址类型检查是否为ACR配置公网的访问控制配置专有网络的访问控制

  5. 仓库认证:如果使用需要认证的私有镜像仓库(非本账号下ACR),请检查在镜像配置中填写的认证信息是否正确。

Q:如何跨地域使用 ACR 镜像?

EAS服务默认能通过 VPC 内网地址拉取同地域 ACR 仓库中的镜像。如果 ACR 实例与 EAS 服务不在同一地域,内网直连不可用。可通过以下方法解决:

  • 方法一(推荐):在 EAS 服务所在地域重新创建 ACR 实例,将镜像推送到同地域仓库后再部署,从根本上避免跨地域问题。

  • 方法二:通过 CEN(云企业网)打通两个地域的 VPC,实现跨地域内网拉取。具体操作参见跨地域或从IDC访问企业版实例

  • 方法三(测试场景):通过公网地址拉取镜像,需确认已为 ACR 开通公网访问,并为 EAS 服务配置能访问公网的 NAT 网关。速度较慢且存在安全风险,仅建议用于测试场景。

Q:部署自定义镜像报错"no match for platform in manifest"怎么办?

该错误表示推送的镜像架构(如arm64)与 EAS 实例的运行环境(通常为amd64/x86_64)不匹配,EAS 无法在该机型上运行此镜像。常见于在 M 系列芯片 Mac(arm64)上构建镜像后部署到 EAS(amd64)实例的场景。解决方法如下:

  1. 确认 EAS 目标实例的 CPU 架构(大多数 EAS 实例为amd64)。

  2. 在本地重新构建与 EAS 实例架构匹配的镜像:

    # 构建 amd64 架构镜像(适用于大多数EAS实例)
    docker build --platform linux/amd64 -t <ACR仓库域名>/<命名空间>/<镜像仓库名>:<版本号> .
  3. 将新镜像推送到 ACR 后,重新部署服务。

Q:ACK 能连接EAS专属镜像库(PAI官方镜像)么?

EAS专属镜像库不支持 ACK 直连,ACK 无法直接拉取EAS专属镜像库中的镜像。

更多问题,请参见EAS常见问题