
# 模型的自定义镜像制作流程
如果您使用了ModelArts不支持的AI引擎开发模型，也可通过制作自定义镜像，导入ModelArts创建为模型，并支持进行统一管理和部署为服务。
![](https://support.huaweicloud.com/docker-modelarts/public_sys-resources/note_3.0-zh-cn.png)
**基础镜像：**镜像制作的一个基本概念，您可以在基础镜像上构建业务镜像。基础镜像可以是ModelArts预置镜像或统一镜像。
#### 制作流程
**场景一：** 预置镜像的环境软件满足要求，只需要导入模型包，就能用于创建模型，通过镜像保存功能制作。具体案例参考[在Notebook中通过镜像保存功能制作自定义镜像用于推理](https://support.huaweicloud.com/docker-modelarts/docker-modelarts_6002.html)。
图1模型的自定义镜像制作场景一   
![](https://support.huaweicloud.com/docker-modelarts/figure/zh-cn_image_0000002556271424.png "点击放大")
**场景二：** 预置镜像既不满足软件环境要求，同时需要放入模型包，新的镜像超过35G，在服务器（如ECS）上制作。具体案例参考[在ECS中通过Dockerfile从0制作自定义镜像用于推理](https://support.huaweicloud.com/docker-modelarts/modelarts_23_0270.html)。
图2模型的自定义镜像制作场景三   
![](https://support.huaweicloud.com/docker-modelarts/figure/zh-cn_image_0000002586951107.png "点击放大")
**场景** **三** **：** 预置镜像既不满足软件环境要求，同时需要放入模型包，在Notebook中通过Dockerfile制作。具体案例参考[在Notebook中通过Dockerfile从0制作自定义镜像用于推理](https://support.huaweicloud.com/docker-modelarts/docker-modelarts_0031.html)。
图3模型的自定义镜像制作场景二   
![](https://support.huaweicloud.com/docker-modelarts/figure/zh-cn_image_0000002625357698.png "点击放大")
#### 约束限制
- 自定义镜像中不能包含恶意代码。
- 创建模型的自定义镜像大小不超过50GB。
- 对于同步请求模式的模型，如果预测请求时延超过60s，会造成请求失败，甚至会有服务业务中断的风险，预测请求时延超过60s时，建议制作异步请求模式的模型。
 
#### 自定义镜像的配置规范
- **镜像对外接口**
  设置镜像的对外服务接口，推理接口需与config.json文件中apis定义的url一致，当镜像启动时可以直接访问。下面是mnist镜像的访问示例，该镜像内含mnist数据集训练的模型，可以识别手写数字。其中listen_ip为容器IP，您可以通过启动自定义镜像，在容器中获取容器IP。
  - 请求示例
    ```
    curl -X POST \ http://{listen_ip}:8080/ \ -F images=@seven.jpg
    ```
    图4listen_ip获取示例   
    ![](https://support.huaweicloud.com/docker-modelarts/figure/zh-cn_image_0000002586791235.png) 
  
  - 返回示例
    ```
    {"mnist_result": 7}
    ```
    
   
- **（可选）健康检查接口**
  如果在滚动升级时要求不中断业务，那么必须在config.json文件中配置健康检查的接口，供ModelArts调用，在config.json文件中配置。当业务可提供正常服务时，健康检查接口返回健康状态，否则返回异常状态。
  ![](https://support.huaweicloud.com/docker-modelarts/public_sys-resources/notice_3.0-zh-cn.png)
  - 如果要实现无损滚动升级，必须配置健康检查接口。
  
  - 自定义镜像如果需要在"在线服务"模块使用OBS外部存储挂载功能，需要新建一个OBS挂载专属目录如"/obs-mount/"，避免选择存量目录覆盖已有文件。OBS挂载仅开放对挂载目录文件新增、查看、修改功能，如果需要删除文件请到OBS并行文件系统中手动删除。
   
  健康检查接口示例如下。
  - URI
    ```
    GET /health
    ```
    
  
  - 请求示例curl -X GET \ http://{listen_ip}:8080/health
  
  - 响应示例
    ```
    {"health": "true"}
    ```
    
  
  - 状态码
    表1状态码 
    | 状态码 | 编码 | 状态码说明 |
    |:---|:---|:---|
    | 200 | OK | 请求成功  |
       
    
   
- **日志文件输出**
  为保证日志内容可以正常显示，日志信息需要打印到标准输出。
  
- **镜像启动入口**
  如果需要部署批量服务，镜像的启动入口文件需要为"/home/run.sh"，采用CMD设置默认启动路径，例如Dockerfile配置如下：
  CMD ["sh", "/home/run.sh"]
  
- **镜像依赖组件**
  如果需要部署批量服务，镜像内需要集成python、jre/jdk、zip等组件包。
  
- **（可选）保持Http长链接，无损滚动升级**
  如果需要支持滚动升级的过程中不中断业务，那么需要将服务的HTTP的"keep-alive"参数设置为200s。以gunicorn服务框架为例，gunicorn缺省情形下不支持keep-alive，需要同时安装gevent并配置启动参数"--keep-alive 200 -k gevent"。不同服务框架参数设置有区别，请以实际情况为准。
  
- **（可选）处理SIGTERM信号，容器优雅退出**
  如果需要支持滚动升级的过程中不中断业务，那么需要在容器中捕获SIGTERM信号，并且在收到SIGTERM信号之后等待60秒再优雅退出容器。提前优雅退出容器可能会导致在滚动升级的过程中业务概率中断。要保证容器优雅退出，从收到SIGTERM信号开始，业务需要将收到的请求全部处理完毕再结束，这个处理时长最多不超过90秒。例如run.sh如下所示：
  ```
  #!/bin/bash
  gunicorn_pid=""
  handle_sigterm() {
    echo "Received SIGTERM, send SIGTERM to $gunicorn_pid"
    if [ $gunicorn_pid != "" ]; then
        sleep 60
        kill -15 $gunicorn_pid  # 传递 SIGTERM 给gunicorn进程
        wait $gunicorn_pid           # 等待gunicorn进程完全终止
    fi
  }
  trap handle_sigterm TERM
  ```
  
 
