更新时间:2025-02-20 GMT+08:00
分享

制作ModelArts集群训练镜像

制作训练镜像

八爪鱼训练镜像使用ma-user用户运行,用户需保证镜像内已创建ma-user用户,且训练过程中使用到的python环境或其他依赖对ma-user具有权限。本地镜像构建完成后,需要将镜像上传到八爪鱼平台镜像仓库。

  • 如果使用dockerfile构建,参考命令为docker build -f Dockerfile -t new_image:1.0
  • 如果使用容器命令行方式构建,参考命令为docker commit {container-id} new_image:1.0

以下分别介绍“从0到1构建”和“从已有镜像迁移”两种制作方式。

  • 从0到1构建训练镜像。

    用户可以docker run -it {image-id-or-name} bash在容器内依次执行命令后commit为新的镜像。

    或者采用dockerfile构建,参考如下:
    # 1、查看算法依赖,一般需要考虑使用的ubuntu版本、cuda版本、cudnn版本
    FROM xxx/cuda:11.3.1-cudnn8-devel-ubuntu20.04
    
    # 2、安装python环境 如果使用其他方式安装,可替换
    USER root
    RUN apt update && \
        apt install python3 python3-pip -y && \
        # 可选,安装opencv库时需要安装以下依赖,缺少其他库请按实际需求添加依赖
        # apt install libgl1-mesa-glx -y && \
        ln -sf /usr/bin/python3 /usr/bin/python && \
        ln -sf /usr/bin/pip3 /usr/bin/pip && \
        # 如果在root下安装pip依赖,在步骤3后需要对python库添加权限,如
        # chmod -R 777 ${PYTHONPATH}/lib/python3.8 或者
        # chown -R ma-user:100 ${PYTHONPATH}/lib/python3.8
        # pip install xxx
    
    # 3、增加ma-user(必选)
    RUN useradd -m -d /home/ma-user -s /bin/bash -g 100 -u 1000 ma-user
    
    # 4、安装python依赖(或可在步骤2中安装)
    USER ma-user
    RUN pip install xxx
    
    ENV PYTHONPATH ${PYTHONPATH}:{YOUR NEW PYTHON BIN PATH}
  • 从已有镜像迁移。
    # 将已有镜像导入
    FROM {YOUR OWN IMAGE}
    USER root
    RUN useradd -m -d /home/ma-user -s /bin/bash -g 100 -u 1000 ma-user
    
    # 此处添加对使用python库赋权限,参考方式一
    # 例如,用户的python依赖均在root属主下,需要对ma-user开放权限
    
    USER ma-user
    ENV PYTHONPATH ${PYTHONPATH}:{YOUR PYTHON BIN PATH}

制作推理服务镜像

  • 推理服务镜像同训练任务镜像一样,必须内置一个用户名为“ma-user”,组名为“ma-group”的普通用户,且必须确保该用户的uid=1000、gid=100。
  • 需要明确设置镜像的启动命令。执行命令为:CMD sh /home/mind/run.sh
  • 服务端必须使用https协议, 且暴露在所有网络平面(0.0.0.0)的“8080”端口。
  • 在“8080”端口,提供URL路径为“/health”的健康检查接口供健康检查使用。
  • 接口仅支持POST、GET、PUT、DELETE四种方法。

    Dockerfile示例:

    FROM python:3.11
    
    USER root
    RUN useradd -m -d /home/ma-user -s /bin/bash -g 100 -u 1000 ma-user
    
    USER ma-user
    RUN pip install --progress-bar off flask cryptography
    
    WORKDIR /home/ma-user
    COPY server.py .
    CMD python server.py

    HTTPS Server示例:

    from flask import Flask, request
    import json 
    
    app = Flask(__name__)
    
    @app.route('/greet', methods=['POST'])
    def say_hello_func():
        print("----------- in hello func ----------")
        data = json.loads(request.get_data(as_text=True))
        print(data)
        username = data['name']
        rsp_msg = 'Hello, {}!'.format(username)
        return json.dumps({"response":rsp_msg}, indent=4)
    
    @app.route('/goodbye', methods=['GET'])
    def say_goodbye_func():
        print("----------- in goodbye func ----------")
        return '\nGoodbye!\n'
    
    @app.route('/', methods=['POST'])
    def default_func():
        print("----------- in default func ----------")
        data = json.loads(request.get_data(as_text=True))
        return '\n called default func !\n {} \n'.format(str(data))
    
    @app.route('/health', methods=['GET'])
    def healthy():
        return "{\"status\": \"OK\"}"
    
    # host must be "0.0.0.0", port must be 8080
    if __name__ == '__main__':
        # 访问创建推理服务时选择的模型版本文件
        torchserve = PTVisionService(model_path=os.getenv('OCTOPUS_MODEL') + '/best.pt')
        
        # host must be "0.0.0.0", port must be 8080
        app.run(host="0.0.0.0", port=8080, ssl_context='adhoc')

    注意:在创建推理服务时选择的模型版本文件将在服务启动时下载到OCTOPUS_MODEL对应的路径下:

    环境变量名称

    含义

    默认值(默认值可能会随版本变化,不建议直接使用)

    OCTOPUS_MODEL

    模型版本文件下载目录

    /home/mind/model

    在本地机器调试

    自定义引擎的规范可以在安装有docker的本地机器上通过以下步骤提前验证:

    1. 将自定义引擎镜像下载至本地机器,假设镜像名为“custom_engine:v1”。
    2. 将模型版本文件夹复制到本地机器,假设模型包文件夹名字为“model”。
    3. 在模型文件夹的同级目录下验证如下命令启动服务:

      docker run -u 1000:100 -p 8080:8080 -v /home/model:/home/mind/model -e OCTOPUS_MODEL=/home/mind/model custom_engine:v1

    4. 在本地机器上启动另一个终端,执行以下验证指令,得到符合预期的推理结果。

      curl -k https://127.0.0.1:8080/${推理服务的请求路径}

      本地调试完成后,每次都需将镜像推送至新版本,使用二次推送镜像功能会导致推理服务镜像更新不生效。

制作开发环境镜像

需要在Dockerfile文件中添加uid为1000的用户ma-user和gid为100的用户组ma-group。如果基础镜像中uid 1000或者gid 100已经被其他用户和用户组占用,需要将其对应的用户和用户组删除。制作开发环境的自定义镜像时,基础镜像需满足如下规范:

  • 使用Dockerhub等官方源发布的镜像。
  • 使用Ubuntu 18.04、Ubuntu 20.04、Ubuntu 22.04作为基础镜像。

Dockfile示例如下,以Ubuntu 20.04为例:

# Replace it with the actual image version.
FROM ubuntu:20.04

# Set the user ma-user whose UID is 1000 and the user group ma-group whose GID is 100
USER root
RUN default_user=$(getent passwd 1000 | awk -F ':' '{print $1}') || echo "uid: 1000 does not exist" && \
    default_group=$(getent group 100 | awk -F ':' '{print $1}') || echo "gid: 100 does not exist" && \
    if [ ! -z ${default_user} ] && [ ${default_user} != "ma-user" ]; then \
        userdel -r ${default_user}; \
    fi && \
    if [ ! -z ${default_group} ] && [ ${default_group} != "ma-group" ]; then \
        groupdel -f ${default_group}; \
    fi && \
    groupadd -g 100 ma-group && useradd -d /home/ma-user -m -u 1000 -g 100 -s /bin/bash ma-user && \

# Grant the read, write, and execute permissions on the target directory to the user ma-user.
chmod -R 750 /home/ma-user

#Configure the APT source and install the ZIP and Wget tools (required for installing conda).
RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak && \
    echo "deb http://repo.huaweicloud.com/ubuntu/ bionic main restricted\ndeb http://repo.huaweicloud.com/ubuntu/ bionic-updates main restricted\ndeb http://repo.huaweicloud.com/ubuntu/ bionic universe\ndeb http://repo.huaweicloud.com/ubuntu/ bionic-updates universe\ndeb http://repo.huaweicloud.com/ubuntu/ bionic multiverse\ndeb http://repo.huaweicloud.com/ubuntu/ bionic-updates multiverse\ndeb http://repo.huaweicloud.com/ubuntu/ bionic-backports main restricted universe multiverse\ndeb http://repo.huaweicloud.com/ubuntu bionic-security main restricted\ndeb http://repo.huaweicloud.com/ubuntu bionic-security universe\ndeb http://repo.huaweicloud.com/ubuntu bionic-security multivers e" > /etc/apt/sources.list && \
apt-get update && \
apt-get install -y zip wget

#Modifying the system Configuration of the image (required for creating the Conda environment)
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

#Switch to user ma-user , download miniconda from the Tsinghua repository, and install miniconda in /home/ma-user.
USER ma-user
RUN cd /home/ma-user/ && \
    wget --no-check-certificate https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-4.6.14-Linux-x86_64.sh && \
    bash Miniconda3-4.6.14-Linux-x86_64.sh -b -p /home/ma-user/anaconda3 && \
    rm -rf Miniconda3-4.6.14-Linux-x86_64.sh

#Configure the conda and pip sources
RUN mkdir -p /home/ma-user/.pip && \
    echo -e "channels:\n  - defaults\nshow_channel_urls: true\ndefault_channels:\n  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main\n  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r\n  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2" > /home/ma-user/.condarc && \
    echo -e "[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple\n[install]\ntrusted-host = https://pypi.tuna.tsinghua.edu.cn" > /home/ma-user/.pip/pip.conf

#Create the conda environment and install the Python third-party package. The ipykernel package is mandatory for starting a kernel.
RUN source /home/ma-user/anaconda3/bin/activate && \
    conda create -y --name pytorch_1_8 python=3.7 && \
    conda activate pytorch_1_8 && \
    pip install torch==1.8.1 torchvision==0.9.1 && \
    pip install ipykernel==6.7.0 && \
    conda init bash && \
    conda deactivate 

#Install packages like FFmpeg and GCC
USER root
RUN apt-get -y install ffmpeg && \
    apt -y install gcc-8 g++-8
  • 如需使用Jupyter功能还需手动添加IPython Kernel并绑定到当前的Python环境保证交互式指令能正常运行,否则打开“JupyterLab > 新建Notebook”会选不到kernel。

    具体步骤可参考在Notebook中添加自定义IPython Kernel

  • 不满足以上镜像规范,所制作的镜像可能会出现故障。常见故障排查:
    • 用户自定义镜像没有ma-user用户及ma-group用户组;
    • 用户自定义镜像中/home/ma-user目录,属主和用户组不是ma-user和ma-group;
    • 用户自定义镜像必须满足用户目录/home/ma-user权限为750,不能为其他权限;
    • 用户自定义镜像使用远程SSH功能,OpenSSH版本要兼容或高于8.0;
    • 用户制作的自定义镜像,在本地执行docker run启动,无法正常运行;
    • 用户自行安装了Jupyterlab服务导致冲突的,需要用户本地使用Jupyterlab命令罗列出相关的静态文件路径,删除并且卸载镜像中的Jupyterlab服务;
    • 用户自己业务占用了开发环境官方的8888、8889端口的,需要用户修改自己的进程端口号;
    • 用户的镜像指定了PYTHONPATH、sys.path导致服务启动调用冲突的,需在实例启动后,再指定PYTHONPATH、sys.path;
    • 用户使用了已开启sudo权限的专属池,使用自定义镜像时,sudo工具未安装或安装错误;
    • 用户使用的cann、cuda环境有兼容性问题;
    • 用户的docker镜像配置错误、网络或防火墙限制、镜像构建问题(文件权限、依赖缺失或构建命令错误)等原因导致的。

相关文档