容器镜像的构建和调试指南
构建镜像:
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以上)。
docker和linux的文件交互命令如下:
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页面确认基础镜像已正常上传
远程调试要点:
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
- 点赞
- 收藏
- 关注作者
评论(0)