使用python3镜像作为基础镜像,把python项目(机器学习训练的代码)打入镜像,最终实现启动docker容器,执行训练任务的目标。本文使用一个小的实例说明,docker镜像制作和通过挂载路径的方式执行docker。
1)使用s2i工具制作镜像
2)使用docker build制作镜像
3) 在原有基础镜像上做修改,docker commit(网上不推荐)
使用第1)或者第2)种方法,都需要写Dockerfile,个人理解Dockerfile类似于图纸,像盖房子,怎么盖,要想象通过Dockerfile制作好的镜像是什么样的,具备什么能力。本文采用,第二种方法,简单一些,第一种方法需要研究研究。
本实例的目的是制作一个模型训练的镜像,一般模型训练的代码会提供一个入口,这个不是我们讲docker 和镜像的重点,我们就叫它 run.sh,执行了run.sh并提供一些参数就可以进行训练任务,参数为模型数据--data_dir,训练好的模型输出路径--output_dir, 预训练模型--model_path。
所以写Dockerfile的思路:
1)引入基础镜像
2)将python源代码(忽略安全问题)拷贝到镜像内,解释一下COPY 命令, COPY src dest, src指的是本地目录,dest指的是docker 镜像里的目录, 注意填写与Dockerfile的相对路径,dest在docker镜像内不用创建,没有路径会自动创建。
3)设置工作目录 后续的路径 都可以在这个工作目录的基础上
3)安装pip依赖,所以最初的Dockerfile应该是这样:
FROM python3
COPY ./ ./App/nlp
WORKDIR ./
RUN pip install -r App/nlp/nlp_huggingface/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
参数通过docker run 将本地目录挂载到镜像中的方式。执行镜像内run.sh 可以通过两种方法:
在Dockerfile中最后补上下面的命令,这样在每次执行docker run
CMD cd ./App/nlp/nlp_huggingface/ && ./run.sh,这样的Dockerfile应该为:
FROM python3
COPY ./ ./App/nlp
WORKDIR ./
RUN pip --default-timeout=100 install -U -r App/nlp/nlp_huggingface/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD cd ./App/msnlp/msnlp_huggingface/ && ./run.sh
本文采取docker build的方法,cd 进入Dockerfile所在的目录,执行下面的命令(不要忘了后面还有个点)
docker build -t nlp_train_image:v1.0 .
Tip:在制作镜像的时候,安装torch等几百兆的包时,会经常因为timeout失败,可以加上 --default-timeout=100 ,就不会因为timeout失败。
下面的一些坑,可能你也会遇到:
假设打好了镜像为nlp_train_image:v1.0,执行docker的命令为:
sudo docker run nlp_train_image:v2.1 -v /home/fuming.ge/data/msraner:/data/msraner /home/fuming.ge/tmp:/tmp -/home/fuming.ge/data/bert/model/bert_base_chinese:/model/bert_base_chinese
但是总是报错:
[root@s01c-nlp]# sudo docker run nlp_train_image:v1.0 -v /home/fuming.ge//data/msraner:/data/msraner /home/fuming.ge/tmp:/tmp /home/fuming.ge/data/bert/model/bert_base_chinese:/model/bert_base_chinese
container_linux.go:235: starting container process caused "exec: \"-v\": executable file not found in $PATH"
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:235: starting container process caused "exec: \"-v\": executable file not found in $PATH".
错误原因:docker run的命令使用方式不对,
解决方法:-v 应该在前面
修改一下,将镜像放到最后,再次执行:
[root@s01cq-F1R18U1821-ai-app-200-12-msxf msnlp]# sudo docker run -v /home/fuming.ge/data/msraner:/data/msraner /home/fuming.ge//tmp:/tmp /home/fuming.ge/data/bert/model/bert_base_chinese:/model/bert_base_chinese nlp_train_image:v1.0
/usr/bin/docker-current: Error parsing reference: "/home/fuming.ge/tmp:/tmp" is not a valid repository/tag: invalid reference format.
可以看出又报错,错误提示"/home/fuming.ge/tmp:/tmp" is not a valid repository/tag,
解决方法:将每个挂载路径都加上-v,
[root@s01cq-F1R18U1821-ai-app-200-12-msxf msnlp]# sudo docker run -v /home/fuming.ge/data/msraner:/data/msraner /home/fuming.ge//tmp:/tmp /home/fuming.ge/data/bert/model/bert_base_chinese:/model/bert_base_chinese nlp_train_image:v1.0
/usr/bin/docker-current: can not find path or file “/data/msraner ”
原因:没有挂载上,原因可能是因为挂载需要镜像内创建相应的目录,修改Dockerfile为:
FROM python3
COPY ./ ./App/nlp
WORKDIR ./
RUN mkdir -p /data/msraner
RUN mkdir -p /tmp
RUN mkdir -p /model/bert_base_chinese
RUN pip --default-timeout=100 install -U -r App/nlp/nlp_huggingface/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD cd ./App/msnlp/msnlp_huggingface/ && ./run.sh
Tip:可以先注释掉 RUN pip install 。。,我们只是验证是不是需要在镜像内创建相应的目录,就可以挂载上,不用pip install,这个花的时间很长
运行成功,训练任务开始执行
[root@s01-nlp]# sudo docker run -v /home/fuming.ge/data/msraner:/data/msraner -v /home/fuming.ge/tmp:/tmp -v /home/fuming.ge/data/bert/model/bert_base_chinese:/model/bert_base_chinese nlp_train_image:v2.1
Iteration: 100%|██████████| 6/6 [00:35<00:00, 5.92s/it]
Iteration: 100%|██████████| 6/6 [00:21<00:00, 3.63s/it]
Iteration: 100%|██████████| 6/6 [00:26<00:00, 4.43s/it]
Epoch: 100%|██████████| 3/3 [01:23<00:00, 27.97s/it]/it]
Evaluation: 100%|██████████| 5/5 [00:06<00:00, 1.35s/it]
{'O': 0, 'B-LOCATION': 1, 'I-LOCATION': 2, 'B-ORGANIZATION': 3, 'I-ORGANIZATION': 4, 'B-PERSON': 5, 'I-PERSON': 6}
{"eval_loss": 0.5701287448406219, "eval_precision": 0.0, "eval_recall": 0.0, "eval_f1": 0, "epoch": 3.0, "step": 18}