当官方镜像无法满足复杂的业务逻辑和环境需求时,可构建自定义镜像封装完整的运行环境。EAS支持使用自定义镜像来部署模型服务。
在服务运行过程中,EAS的服务引擎会以Sidecar方式注入服务实例,主要进行流量或系统监控数据的采集,以及对服务请求增加认证信息等。镜像部署支持在镜像中以HTTP、WebSocket、gRPC(HTTP2)三种协议提供API服务。
镜像仓库使用说明
容器镜像服务ACR
推荐使用VPC地址拉取镜像。
重要公网拉取镜像存在安全风险,且速度会特别慢,不建议使用。同时EAS默认不可访问公网,如需通过公网拉取镜像仓库,请参见让EAS服务访问公网。
ACR个人版:只能在一个地域内开通使用,跨地域拉取镜像只能通过公网地址。建议仅在测试场景使用ACR个人版,并确保与EAS服务同地域。
ACR企业版:
使用VPC地址,需为EAS配置VPC专有网络,为ACR配置专有网络的访问控制。如跨地域,需通过CEN打通VPC,参见跨地域或从IDC访问ACR企业版实例。
使用公网地址,需为EAS配置能访问公网的VPC专有网络,为ACR开通公网访问。
使用同账号下的ACR镜像仓库部署时,无需填写用户名密码,EAS可实现跨服务免密拉取。
自建镜像仓库
阿里云VPC中使用Harbor自建的镜像仓库,地址仅支持在VPC中访问,与ACR企业版类似,需要打通EAS到您的VPC网络,详情请参见让EAS服务访问VPC内网资源。
若自建仓库需要用户名密码访问,则在服务部署时需提供用户名密码信息。注意JSON配置文件中需以Base64编码
username:password
,详情请参见部署模型服务章节的dockerAuth参数说明。
准备工作
如果您已经有一个开发好的镜像,并能够提供HTTP、WebSocket、gRPC协议的访问,则可跳过该章节。
1. 准备代码与模型文件
以一个简单的Flask Web 服务为例,代码文件app.py
内容如下。
from flask import Flask
app = Flask(__name__)
@app.route('/hello/model')
def hello_world():
# 这里是模型推理或其他业务逻辑
return 'Hello World'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
此处省略了模型处理的逻辑,为了提高部署效率和灵活性,建议将体积较大的模型文件(通常大于1GB)存储在对象存储OSS(Object Storage Service)中,而不是直接打包进镜像。在EAS部署时,通过挂载OSS的方式将模型加载到服务中,参见服务存储挂载。
例如:将模型 my_model.pth
存放在 oss://my-bucket/models/
目录下,并将此目录挂载到容器目录/mnt/data
。在代码中,您可以通过绝对路径 /mnt/data/my_model.pth
来直接访问它。
2. 构建镜像
如果使用DSW开发,在DSW实例的操作列中单击制作镜像,系统将构建Docker镜像并保存到阿里云容器镜像服务ACR中,部署时选择自定义镜像即可下拉选择。详情请参见制作DSW实例镜像。
下文介绍本地安装Docker并构建镜像。也可以使用如阿里云容器镜像服务ACR进行镜像构建。
编写Dockerfile文件。
Dockerfile是一个包含了构建镜像需要的指令和说明的文本文件。在
app.py
文件同级创建Dockerfile文件,文件目录结构如下:flask_app ├── app.py └── Dockerfile
以下Dockerfile示例文件中,将代码文件
app.py
打包在待部署的镜像中,也可以保存在OSS、NAS或Git仓库中,通过存储挂载的方式在运行时挂载进服务实例。# 说明该镜像以哪个镜像为基础 FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/python # 在容器内部执行的命令 RUN yum -y install python3-pip RUN pip3 install flask # 创建 app 文件夹 RUN mkdir -p /app # 进入 app 目录 RUN cd /app # 将 linux 系统当前目录下的app.py拷贝到容器的 /app 目录下 COPY app.py /app/ # 暴露 8000 端口 EXPOSE 8000 # 将 app 文件夹为工作目录 WORKDIR /app # 容器启动的时候执行的命令 flask run CMD ["flask", "run", "--host", "0.0.0.0"]
构建本地镜像。在命令行中,进入目录flask_app,执行以下命令构建一个名为flask-app的Docker镜像。
docker build -t flask-app .
3. 推送镜像到仓库
执行命令
docker images
可以获取构建的镜像ID。假设使用ACR个人版,地址为
crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***
。执行以下命令,将镜像推送到ACR镜像仓库。
docker login --username=<用户名> crpi-***.cn-hangzhou.personal.cr.aliyuncs.com docker tag <镜像ID> crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app docker push crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app
则该镜像的镜像地址为:
crpi-***.cn-hangzhou.personal.cr.aliyuncs.com/***/***:flask-app
。
部署模型服务
将上述镜像进行部署,相关参数取值如下:
镜像地址:
crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app
。镜像的启动执行命令:
python3 app.py
。镜像中进程监听的网络端口号:8000。
说明端口号在一些场景中为可选。例如,在用户服务中不依赖由EAS网关导入的流量,而是用户在镜像中自行通过订阅消息队列的方式获取消息,则此场景中镜像端口号可选填。
使用控制台部署
关键参数配置如下:
部署方式:选择镜像部署。
镜像配置:选择镜像地址,填写:
crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app
。示例使用ACR镜像仓库,不需要填写用户名密码。运行命令:
python3 app.py
端口号:8000。
使用客户端工具部署
JSON配置文件如下:
{ "metadata": { "name": "flask_app_test", "instance": 1 }, "cloud": { "computing": { "instances": [ { "type": "ecs.c8y.large" } ] } }, "containers": [ { "image": "crpi-***-vpc.cn-hangzhou.personal.cr.aliyuncs.com/***:flask-app", "script": "python3 app.py", "port": 8000 } ] }
关于自定义镜像部署的关键参数说明如下表所示。更多参数说明,详情请参见JSON部署。
参数
是否必选
描述
containers
image
是
用于部署模型服务的镜像地址。
command
二者必选其一
镜像的入口命令,只支持单一命令形式,不支持复杂脚本,如:cd xxx && python app.py,这种形式请使用下面的script参数来指定,command字段适应于镜像中无/bin/sh命令的场景。
script
镜像的入口执行的脚本,可指定较为复杂的脚本形式,多行以\n或分号分隔。
port
否
容器端口。
重要由于EAS引擎监听固定的8080/9090端口,因此容器端口需要避开8080/9090端口。
该端口一定要和command中的xxx.py文件配置的端口保持一致。
dockerAuth
否
如果使用私有仓库中的镜像,则需要通过该参数指定Docker Registry的认证信息。目前,认证信息仅支持
username:password
的Base 64编码形式。例如,
username:password
取值为abcd:abcde12345
时,命令echo -n "abcd:abcde12345" | base64
返回YWJjZDphYmNkZTEy****
,即为dockerAuth的取值。通过客户端工具的
create
命令部署模型服务。需先下载并认证客户端。eascmd create image.json
其中image.json表示上一步中创建的服务配置JSON文件。
系统返回如下类似结果,包括服务的访问地址和访问Token。
[RequestId]: BFFFE5F5-1F07-437E-B59A-AF1F2B66**** +-------------------+-----------------------------------------------------------------------------------+ | Internet Endpoint | http://182848887922***.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test | | Intranet Endpoint | http://182848887922***.vpc.cn-shanghai.pai-eas.aliyuncs.com/api/predict/image_test| | Token | NjA4MzQxOWQ0MTY2M2Y4OGY0NjgwODkwZTZmYWJmZWU1ZmY0Njhk**** | +-------------------+-----------------------------------------------------------------------------------+ [OK] Service is now creating [OK] Waiting [Total: 2, Pending: 2, Running: 0] [OK] Running [Total: 2, Pending: 0, Running: 2] [OK] Service is running
如果需要修改服务配置,则通过客户端工具的
modify
命令实现。修改上述服务的示例命令如下,关于
modify
命令的详情信息,请参见修改服务配置。eascmd modify registry_test -s image.json
其中:registry_test表示服务名称;image.json表示服务描述文件。
服务验证
当服务状态变为“运行中”时,表示服务已成功启动。上述flask-app镜像提供了一个Web服务,访问路径为/hello/model
,故可通过如下命令进行调用测试:
curl <endpoint>/hello/model -H "Authorization: <token>"
其中:<endpoint>
和<token>
替换为服务的实际调用地址和Token,参见获取访问地址和Token。
关于服务请求的更多信息,详情请参见服务调用方式。
常见问题
镜像拉取失败等问题,请参见EAS常见问题。