容器镜像的构建和调试指南

举报
yangzilong 发表于 2021/07/20 10:54:26 2021/07/20
【摘要】 在ModelArts服务中进行训练和推理都支持使用自定义的容器镜像。 本文介绍了构建容器镜像以及调试镜像的全过程,可以辅助用户快速构建一个深度学习的自定义容器镜像。

构建镜像:

1.通过Dockerfile【调试时不推荐,正式归档时推荐】:

1.1 写一个Dockerfile,参考:

FROM swr.cn-north-4.myhuaweicloud.com/modelarts-job-dev-image/custom-cpu-base:1.0

# setup the env that you need when running a container
ENV PYTHON_PATH=/mypath/:$PYTHON_PATH

# copy local files (code, packages, or data) into container images
COPY install/ /home/work/install/
# run shell comment to install packages or setting up configs
RUN cd /home/work/install && pip install -r requirements.txt --no-cache-dir && \
    cd /home/work/install/obs_sdk/src && python setup.py install

1.2 把要打到基础镜像的依赖包跟Dockerfile放在同一目录,cd到这个目录,执行打镜像命令:

docker build -t my_deeplearning_image:v1 .

2.通过docker commit命令【调试时推荐,正式归档不推荐】:

docker commit -a 'image author' -m 'message of change' 39c9ceedb1f6 my_deeplearning_image:v1

其中,"39c9ceedb1f6"是后续样例中启动的容器实例id。

不推荐此种方式的原因是对应镜像无法通过代码方式追溯,容易因为人员流动等原因导致对应镜像内容难以迭代。

3.其他镜像构建注意事项:

容器镜像的大小建议小于15G,不能超过30G。否则镜像的迁移、拉起都会存在性能问题。

建议通过开源的官方镜像来构建,例如pytorch的官方镜像、NVIDIA的官方镜像。

建议容器分层构建,单层容量不要超过1G、文件数不大于10w个。分层时,先构建不常变化的层,例如:先OS,再cuda驱动,再Python,再pytorch,再其他依赖包。

不建议把数据、代码放到容器镜像里。因为对应内容应该是经常变动的,会导致频繁的容器镜像构建操作。

不建议在容器内再创建多个conda env。因为容器已经能满足隔离需求,没有必要再通过conda env做隔离。


启动容器:

('-d'参数标示后台启动,不用再新起窗口执行)

docker run -ti -d my_deeplearning_image:v1

如果在调试中需要用到GPU设备,建议使用nvidia-docker来启动。nvidia-docker的安装和使用教程参考链接:https://blog.csdn.net/zywvvd/article/details/110647382

 

进入容器:(一般会另起一个窗口,在debug时使用)

1.获取容器ID

通过命令查看CONTAINER ID ,命令如:

docker ps

结果如:

CONTAINER ID      IMAGE        COMMAND        CREATED        STATUS        PORTS       NAMES
39c9ceedb1f6    my_deeplearning_image:v1    "bash"   About a minute ago   Up About a minute                     happy_meitner

2.进入容器内部

使用以下命令可进入容器内部(使用container ID)

docker exec -it 39c9ceedb1f6 /bin/bash

进入容器后,就类似通过ssh登陆了一个linux机器,可以查看所需的文件是否在正确位置,是否有正确权限。

 

本地调试要点:

0.确认对应的脚本、代码、流程在linux服务器上运行正常。

如果在linux服务器上运行就有问题,那么先调通以后再做容器镜像。


1.确认打入镜像的文件是否在正确的位置,是否有正确的权限。

训练场景主要看一下自研的依赖包是否正常,看一下pip list是否包含所需的包,看一下容器直接调用的python是否是自己所需要的那个(如果容器镜像装了多个python,需要设置python路径的环境变量)。

推理场景主要看一下模型包位置是否正确,看一下python相关是否正确。


2.测试训练启动脚本

2.1优先使用手工进行数据拷贝的工作并验证

一般在镜像里不包含训练所用的数据和代码,所以在启动镜像以后需要手工把需要的文件拷贝进去。建议数据、代码和中间数据都放到"/cache"目录,防止正式运行时磁盘占满。建议linux服务器申请的时候,有足够大的内存(8G以上)以及足够大的硬盘(100G以上)。

dockerlinux的文件交互命令如下:

docker cp data/ 39c9ceedb1f6:/cache/

数据准备完成后,启动训练的脚本,查看训练是否能够正常拉起。一般来说,启动脚本为:

cd /cache/code/
python start_train.py

如果训练流程不符合预期,可以在容器实例中查看日志、错误等,并进行代码、环境变量的修正。

2.2然后预制脚本测试整体流程

一般使用run.sh封装训练外的文件拷贝工作(数据、代码:OBS-->容器,输出结果:容器-->OBS),run.sh的构建方法参考之前的博客:https://bbs.huaweicloud.com/blogs/281792

如果预制脚本调用结果不符合预期,可以在容器实例中进行修改和迭代。

2.3针对专属池场景

因为专属池支持SFS挂载,所以代码、数据的导入会更简单。我们甚至不用再关注OBS的相关操作。 

可以直接把SFS的目录直接挂载到调试节点的"/mnt/sfs_turbo"目录,或者保证对应目录的内容和SFS盘匹配。

调试时建议使用接近的方式,即:启动容器实例时使用"-v"参数来指定挂载某个宿主机目录到容器环境。

docker run -ti -d -v /mnt/sfs_turbo:/sfs my_deeplearning_image:v1

上述命令表示把宿主机的"/mnt/sfs_turbo"目录挂载到容器的"/sfs"目录,在宿主机和容器对应目录的所有改动都是实时同步的。


3.分析错误时:训练镜像先看日志,推理镜像先看API的返回。

可以用过命令查看容器输出到stdout的所有日志:

docker logs -f 39c9ceedb1f6

一般在做推理镜像时,部分日志是直接存储在容器内部的,所以需要进入容器看日志。注意:重点对应日志中是否有ERROR(包括,容器启动时、API执行时)。


4.牵扯部分文件用户组不一致的情况,可以在宿主机用root权限执行命令进行修改

docker exec -u root:root 39c9ceedb1f6 bash -c "chown -R ma-user:ma-user /cache"


5.针对调试中遇到的错误,可以直接在容器实例里修改,修改结果可以通过commit命令持久化。

最终建议把修改点通过dockerfile固化到容器构建正式流程,并重新测试。

 

上传镜像:

完成调试后,需要上传基础镜像到SWR

1.登陆SWR,login的账号密码可在SWR页面的客户端上传指导时生成。

其他账号创建方法:获取长期login指令


2.创建自己的组织(仅需要创建一次)

3.上传镜像(认为${image_name}:${image_version}是刚做好的基础镜像)

先打tag,然后push。注意,第一次使用需要在SWR先创建一个组织,详细参考SWR文档:https://support.huaweicloud.com/usermanual-swr/swr_01_0014.html

docker tag ${image_name}:${image_version} swr.cn-north-4.myhuaweicloud.com/${organization_name}/${image_name}:${image_version}
docker push swr.cn-north-4.myhuaweicloud.com/${organization_name}/${image_name}:${image_version}

4.在SWR页面确认基础镜像已正常上传

 1639123064790061803.png

远程调试要点:

1.直接使用对应镜像创建训练任务即可

针对专属池场景,应注意挂载的目录设置和调试时一致。


2.观察训练任务是否正常执行

主要观察日志是否正常,然后看一下整个任务是否能够正常产出结果。


3.针对观察发现的问题,增加相关信息打印

可以通过在镜像里修改run.sh(重新构建镜像),或者在运行命令里用sed修改run.sh,或者通过增加“env”命令来查看容器环境信息。

如果输入输出的逻辑不是很确认,可以先把样例的数据和代码放到镜像里,先看一看整个训练流程是否可以正常运行。

 

删除本地镜像:

参考:https://blog.csdn.net/winy_lm/article/details/77980529

1.查看是否有对应容器

docker ps -a

2.停止对应容器

docker stop ${container_id}

3.删除对应容器

docker rm ${container_id}

4.删除对应镜像

docker rmi ${image_id}

 

镜像到导出和导入:

如果需要进行镜像的离线迁移,需要用到镜像的导出和导入的功能。

用save保存镜像,用load导入:

docker save ${image_name}:${image_version} > my_deeplearning_image.1.0.tar
docker load -i my_deeplearning_image.1.0.tar

export保存container

docker export ${container_id} > my_deeplearning_image.export.tar

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。